From de37248749afb96a419ff774cbeb9bbfa0a5a55f Mon Sep 17 00:00:00 2001 From: therealyingtong Date: Thu, 4 Nov 2021 12:07:27 +0100 Subject: [PATCH 01/59] Allow passing CellValue as input word to Poseidon gadget. Update circuit description. --- src/circuit.rs | 31 ++------------- src/circuit/gadget/poseidon.rs | 14 ++++--- src/circuit/gadget/poseidon/pow5t3.rs | 23 +++++++++--- src/circuit_description | 54 +++++++++++++-------------- 4 files changed, 55 insertions(+), 67 deletions(-) diff --git a/src/circuit.rs b/src/circuit.rs index de2f819e..d011293c 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -40,10 +40,7 @@ use gadget::{ chip::{EccChip, EccConfig}, FixedPoint, FixedPointBaseField, FixedPointShort, NonIdentityPoint, Point, }, - poseidon::{ - Hash as PoseidonHash, Pow5T3Chip as PoseidonChip, Pow5T3Config as PoseidonConfig, - StateWord, Word, - }, + poseidon::{Hash as PoseidonHash, Pow5T3Chip as PoseidonChip, Pow5T3Config as PoseidonConfig}, sinsemilla::{ chip::{SinsemillaChip, SinsemillaConfig, SinsemillaHashDomains}, commit_ivk::CommitIvkConfig, @@ -485,30 +482,8 @@ impl plonk::Circuit for Circuit { let nf_old = { // hash_old = poseidon_hash(nk, rho_old) let hash_old = { - let message = [nk, rho_old]; - - let poseidon_message = layouter.assign_region( - || "load message", - |mut region| { - let mut message_word = |i: usize| { - let value = message[i].value(); - let var = region.assign_advice( - || format!("load message_{}", i), - config.poseidon_config.state[i], - 0, - || value.ok_or(plonk::Error::SynthesisError), - )?; - region.constrain_equal(var, message[i].cell())?; - Ok(Word::<_, _, poseidon::P128Pow5T3, 3, 2>::from_inner( - StateWord::new(var, value), - )) - }; - - Ok([message_word(0)?, message_word(1)?]) - }, - )?; - - let poseidon_hasher = PoseidonHash::init( + let poseidon_message = [nk, rho_old]; + let poseidon_hasher = PoseidonHash::<_, _, poseidon::P128Pow5T3, _, 3, 2>::init( config.poseidon_chip(), layouter.namespace(|| "Poseidon init"), ConstantLength::<2>, diff --git a/src/circuit/gadget/poseidon.rs b/src/circuit/gadget/poseidon.rs index 8e6cd7c0..aa62013c 100644 --- a/src/circuit/gadget/poseidon.rs +++ b/src/circuit/gadget/poseidon.rs @@ -12,6 +12,7 @@ use halo2::{ mod pow5t3; pub use pow5t3::{Pow5T3Chip, Pow5T3Config, StateWord}; +use crate::circuit::gadget::utilities::CellValue; use crate::primitives::poseidon::{ConstantLength, Domain, Spec, Sponge, SpongeState, State}; /// The set of circuit instructions required to use the Poseidon permutation. @@ -19,7 +20,7 @@ pub trait PoseidonInstructions, const T: usize, Chip { /// Variable representing the word over which the Poseidon permutation operates. - type Word: Copy + fmt::Debug; + type Word: Copy + fmt::Debug + From>; /// Applies the Poseidon permutation to the given state. fn permute( @@ -60,6 +61,7 @@ pub trait PoseidonDuplexInstructions< } /// A word over which the Poseidon permutation operates. +#[derive(Debug)] pub struct Word< F: FieldExt, PoseidonChip: PoseidonInstructions, @@ -149,13 +151,13 @@ impl< pub fn absorb( &mut self, mut layouter: impl Layouter, - value: Word, + value: CellValue, ) -> Result<(), Error> { match self.sponge { Sponge::Absorbing(ref mut input) => { for entry in input.iter_mut() { if entry.is_none() { - *entry = Some(value.inner); + *entry = Some(value.into()); return Ok(()); } } @@ -168,11 +170,11 @@ impl< &mut self.state, input, )?; - self.sponge = Sponge::absorb(value.inner); + self.sponge = Sponge::absorb(value.into()); } Sponge::Squeezing(_) => { // Drop the remaining output elements - self.sponge = Sponge::absorb(value.inner); + self.sponge = Sponge::absorb(value.into()); } } @@ -250,7 +252,7 @@ impl< pub fn hash( mut self, mut layouter: impl Layouter, - message: [Word; L], + message: [CellValue; L], ) -> Result, Error> { for (i, value) in array::IntoIter::new(message).enumerate() { self.duplex diff --git a/src/circuit/gadget/poseidon/pow5t3.rs b/src/circuit/gadget/poseidon/pow5t3.rs index e07504a3..8050919e 100644 --- a/src/circuit/gadget/poseidon/pow5t3.rs +++ b/src/circuit/gadget/poseidon/pow5t3.rs @@ -431,6 +431,12 @@ impl From> for CellValue { } } +impl From> for StateWord { + fn from(cell_value: CellValue) -> StateWord { + StateWord::new(cell_value.cell(), cell_value.value()) + } +} + #[derive(Debug)] struct Pow5T3State([StateWord; WIDTH]); @@ -626,7 +632,10 @@ mod tests { use super::{PoseidonInstructions, Pow5T3Chip, Pow5T3Config, StateWord, WIDTH}; use crate::{ - circuit::gadget::poseidon::{Hash, Word}, + circuit::gadget::{ + poseidon::Hash, + utilities::{CellValue, Var}, + }, primitives::poseidon::{self, ConstantLength, P128Pow5T3 as OrchardNullifier, Spec}, }; @@ -783,22 +792,24 @@ mod tests { |mut region| { let mut message_word = |i: usize| { let value = self.message.map(|message_vals| message_vals[i]); - let var = region.assign_advice( + let cell = region.assign_advice( || format!("load message_{}", i), config.state[i], 0, || value.ok_or(Error::SynthesisError), )?; - Ok(Word::<_, _, OrchardNullifier, WIDTH, 2> { - inner: StateWord { var, value }, - }) + Ok(CellValue::new(cell, value)) }; Ok([message_word(0)?, message_word(1)?]) }, )?; - let hasher = Hash::init(chip, layouter.namespace(|| "init"), ConstantLength::<2>)?; + let hasher = Hash::<_, _, OrchardNullifier, _, WIDTH, 2>::init( + chip, + layouter.namespace(|| "init"), + ConstantLength::<2>, + )?; let output = hasher.hash(layouter.namespace(|| "hash"), message)?; layouter.assign_region( diff --git a/src/circuit_description b/src/circuit_description index 509f45df..552652ad 100644 --- a/src/circuit_description +++ b/src/circuit_description @@ -28325,15 +28325,15 @@ PinnedVerificationKey { (0x05f5862cad2888855bc3c1843a9eff57b11b592d9eb0e13354256661387f5231, 0x32236b14df85bf5f532a930232cb23a5c56ef7d67aaeed8bcb8fc10ea132cbd6), (0x3e727e8554679f98120355d39d958dbd8755d5a7f8b42ea87f258064c4b3eb57, 0x0c0d5c23f3ee62ac1b2d986dd3033bbcab260d590e1393de3a14a4b31ae091bb), (0x3748680dd6a91c5dec668b30fb6bf9a450aeb884b81cbc344914f265760e7131, 0x18530eaa5c58b61bd3fc38220ea484c0922524a815a8f752be955c229f9c4164), - (0x0ba01714529dc85dd2460cdbf014b71e7638d18a35eacf06868020c27c28232d, 0x2dcbb2c3191f582b6882cc9c5e6cac1a0361d0534f8f4c814e33a272b8e8da8d), - (0x0f8fb02c096c0957230639133087e8ae516d04d1678ace6ab0495a8e8576c0db, 0x2842b28258744140b09e0d27559d84e1d8f1d55350b0af37237879d14f8eb2a1), - (0x36f2f0410d5ab00d5296bf101cbd91008551d4afe2b5ac45fc437aa157c731aa, 0x19e8c688f0c92a3db3e74b66075d2e0771d5c744e77090c487ffca245a7f7f96), - (0x09ce7fd65bf8af2b554230465003160d3d0b7bfc495f6d33f5f0704cb57d6320, 0x38d3478df8841a4f7a74a3c1fe7788e6e1cbb1076d5f7358be729fa2572c9530), - (0x2abaec8c54bde721f7f2aea685764c80b0b935447c00173ff34209ac8d96b633, 0x36957cf784345bfbdb97f0fad0b74d3e5d683fcc80ee407d6a6bedfe097c0011), - (0x3f1845e758196892c66d920980dc29cc2e1844fa03575668bf84349071094207, 0x1873355bc49aeed1faee56e6d21907a5277fcd0283a3f51fface877e1c59f046), - (0x04e5834f610cf806911a2e9c14519132a49ac55f40095c3156e3b20d09a2f250, 0x2ea666b99d148e1090b42fd2f67fd34c7e94ca505447c1431485eca09ed1fe0b), - (0x35de09079a5b05d25f756479ea044c654c97043bc4a79b34f860faa9b049337a, 0x06c4cc500093cfdc9bd284f3c44a2a8856cfc8ce70786dd65787397292e4fe53), - (0x235b63a940346f07c5a669831067ba59acb3b9936db7d66c4a4cf6746af5f97e, 0x0d838f859fb1386034263d43ace744961a310f548f7274586f133aa4ddc779a9), + (0x18cd12d5f4e12bd7247a8fd7cc93ded7a8a9b60935b319b2db578a8fceef9559, 0x16b15af4fcfb9ed75533e7a4c1966cae5621f10dc1dfbba39a491ec37c911b5e), + (0x37e70146801841d95832259e4d8f39aeee8a364ea5007f82aa84a0e387231315, 0x20ef65833381c985722a95e65125a1123cab3357741168a5ed7e92e972dbd30d), + (0x12e3af8e507a2ca30e544568cf319701ecbc29dc5919f0198d541938edecc8f3, 0x3fb1bb2804faaa4c215e93694d5d1e6f87874cb8c34cb9206ff958de14e44275), + (0x334d99f316343f01c8eb67e327c76f743f8de7f957c893c6f30ccd87e5d1af3a, 0x1da64caf127c8eb513653791147a85ed1edcca12935c95b7d615a9377c9406d8), + (0x1430dca15080286939046d3cb9fb7ace4ed1da2fbe7a362e8f3575489bc6e3e1, 0x1ef5f4aff2902f3bc8acb2cc884a2d44334f910a68b2701f1c37943652b46d8f), + (0x02ebdeac7e91b3d15e4b7c0533e42678672ec384d51e51e22342be7edeeb8074, 0x03638952e0489de03ff03236433f5d2617cb4ddd0a72637ed31095deca85a2a6), + (0x31179b7f5b01ad2a55cf9a66f57b696e9b9cb4919cca426d469b270827f3018b, 0x2b231a9a71b674cc546ba9b36916a13411648903cfdcb808926fc47ee745586c), + (0x0673497660cec8a8c391cfb16f5ffdcb710f9e9e194a1a85935cf4bc45b01359, 0x15ce8801c51811f0256a43f762e497fe38c88866c09bb256289d93e0393dc225), + (0x098d2a0cfedae91fe29e21a01b5e43045b9cc8d9a334f1aee3e075f36a16e323, 0x0be47cc41643c9e6d95012428d5b46ae5a44e765392e05152a0181e30689d8b6), (0x02adb7cbc9ebbbd87d7d6a41fc40cb4cf57585c6243aa204f757c9026ef20fd3, 0x327fc06fee179c6a57ed95336f9fb7854420d80dd191251a40935664ff6c8067), (0x2d00d4ec8aa5e4b3d035131f559e4a97f896e8dbc39badb92b58a8d46b5e91df, 0x37046fb32ed8eb4ba0b4da8e1c9b56cd3832fa2ed4788f7faf4fee1f76a94c32), (0x212f5afd70e787e2fd951e0ddc5430d1fa78f988c30740384d18cf9ff276b43b, 0x20c5a150e200caddf9a35a993668fc4742be5d924d1086f05c74ef6a78b5feb2), @@ -28342,30 +28342,30 @@ PinnedVerificationKey { (0x13d0bd76da4ace22c0e90b098d6073551322b8c734bf37eeca67fbf19687f550, 0x3d996cc9da5a31cefb453390b906eabbcc75797bc6a6b9c9e3af2fe7b6b8beed), (0x04cad7405b492a30db0a710c842cecc97d02059acf4c02aa79626dce68ac4837, 0x3d6d7b6698b258e61ebe0b25d9cbcd4a016cb0a2ae8d92752532d98cfb27720d), (0x0974ad1a3c0eb4c8d2c59cd820a82b7f28ea2f7a245008d403815131ff30879e, 0x00bb593cdf920cef4965f788d65eba3c3aa07d9718dfb62e3e385849a0d692a8), - (0x3806a39c587dc730cc767713a1ed65cb3171b2b731553d39b84d0896ed46bad9, 0x2b187668497f037b5a72aeeca3b642efc01f536ec6c368c5eef2fe9d54c6cfbb), - (0x171ba8f97a0e12f975056bfb652b5667bc6e2759c4d4fb4de17064ecb60beeaf, 0x055bd6ea2501053cb07723245da65bd46a5bccd52d12073d76ce92e46ab29686), + (0x129898b6bcca9f9ff44f5dc76cb26bc229fa8b14ff47d9153680b0ba5c5efbf6, 0x1be1a12569bd9d26ac6225d404a52099198520eebec3ae1ef5de8a18d74b6116), + (0x3f30174d44efaca9cb31c8b6b6f4f4aaeedba6a974ea72f16ea9259099054bdc, 0x1f0de3c85053cd0d1f07c5edeb276c03c9c8614e78736626d7024eb6987c24ed), (0x1e355d783cffccafc120f462461fb312773442762383ac444009653f3d8d4be6, 0x3c60e17b18492aa2c41798b409d2bcc1857ca57ee9d2fb0001584cedc8e141d6), (0x32059fe4e96eb002f24f6e6090014f7b3baf23946cc31a11341543a5a184903c, 0x3793fd512a65c7aa7c17a42e855eb8be26aa644165a9bc963c368baf0e5cce9d), (0x0a6fe1cc1ce659681079768ca8ff94d82c7d51ef39cd99b738b144de3a3027f6, 0x30cfc2f4e0ec95f623199970d8b762647ad2d7c3591a20781ee8187702babe5f), - (0x29085e497c6097147a72a256459a7237a9bc8cb8e66b56a60f4839468f50ab7b, 0x3a8f21bdd0be7b7d0f641745f5008eedf16f02f04df65691045ef7b21d91443c), - (0x1fcae59b79411349d85836f3dfcba5ab523c2aa1426f62ddf80b7f85e41dfce5, 0x3d0eeb91ef1e68f59a6aead5c4e536f7d6a78721666002d0a92b0b923def40c7), - (0x161c09589b8e0e1d1712b98a4b5cea260d48365ab3f2bba6faec85a2b1966fe6, 0x29e201d0935308e8b1b04ef13c0b9b6891948f69da260bc5c8b12b62aa21155d), - (0x0e6d6b798948be5e9577257fcac9226c659ba7d6040b3b5d0c2df7bf541f18b7, 0x169ba3030178091cce287c13af9b83b376988cc95bc0aa51ea387be0e74964dd), + (0x00d87a2c430f1db50a63f18f8cf8807f4f70d3acb940d4130ba6811f8ba2d479, 0x13d5742320e1b2cecda6073b7f2bf5816b9067453deeaa829f356a65ef5621b2), + (0x3118979ade023f3977d034f86eed6506d7e0586ead81f80bc5ca01a7660ee0c9, 0x30f6731193d5c786cf61b05523c05e2664a066c2d39a685588f02883057320ad), + (0x0df51bd411d5f95da66fcc57f5e4d8dbcca3d82b08ceb61e9ff1befa074e08d3, 0x11c9092b6d02c46f173b0108854499ca4922afaf58e0734e77a6088715e84b64), + (0x24289014ede2672df8e8e32eb4e0d71709846041319fb85b1328cdb3b8764565, 0x0833de9c0b76ae816df0e41ae33daece27c63a41f2ba9abbbc7c08724211b50c), ], permutation: VerifyingKey { commitments: [ - (0x0fbd38d3edc5a2548fee21b4aaab8548eb717b2866c3e7905def92ab41123bd3, 0x1f6d299f0181a6cae84d84c093e68e459271fabef938368eb71c928f351e275d), - (0x29f078d82ad78281cabc78f49c808c4f86b22bd4029b3c03c14e2d5d105eeff0, 0x28f20d695afaed04cda27e52460e71c7ddac016f56fba5730c780bb79304b26e), - (0x3b499a325a876c16aaa0a7621b772c600fd310ef3b690a247fbd4cb270a9a127, 0x1c080b1d2561f1283dab49893a96084b421c501f3b52f28a4afb86a90dcad65e), - (0x255ee788dfb0159fd0b0f5f09d1c69e4ec67337a48a75636f52e8bf6efe8994c, 0x09093cdab6ef83ac64bde2b2252a91944801c8d3e0877c526e592f3d6aca168d), - (0x1f86b1c66c980456a5f80fad06bb3ba739590e53951e2ca40aef5157cb637639, 0x20b35b7cd45a239671f7ccf917411f4f703630b4dc9d41192b44f0d84eac59c0), - (0x046fee5aff0ed40810369bbc1d76f9832fc38ae5ea6d5804e5908e162cbb44ae, 0x07ece7ed5973a1c46b3302ea4cca43b9a7f55f2f5d75cab755860ad65928de17), - (0x02f0c3fbef4a3d9ca3a5a8367285040bc7e2e3837adf0decc601f5ca52986667, 0x1b287e8f1d2812e2051d31e0b8f5b44ad8a42c28b3f23b39f9dab54040197c10), - (0x0a25c502dd5fbc50d0b9bc0c4b73ebdb68212cb3d8919d304366a95cca9273cf, 0x10d56a7902ae750304bb5b397a442e7bb20de731ef393bd5a4bde4b821676f43), - (0x2ce5cc97761c46326b70b86b5c7f5a2b6835ecfc5b19735bc6d69be9d53236c4, 0x182442dbc817aa8926dc78761be286048ac57fd15d5c9e72210013dd77d68a79), - (0x0babcc3c20e0909cfd33f33b2afd5ef7928e935655614a7783a41d54783b8641, 0x1203a94185e9c222b2965adf896f2c7093f151f73f141cb0b6275a9428d56046), - (0x24836d91a72ea59da98dbecda06b12fdfe73bf870cba478b5da6e5a0214c6d42, 0x1d3848af33d96a5fce26243cf19c147260ab903a275bf9a03ff3db91f6a22971), - (0x319f25dcc4b43eaf7767eb2330cb1f31d8790418bd073cb0c03d6c0dcfbdf3c8, 0x1de3e74aee1b1d661c73d0a86c5bf718a76d55ab446973fd2a8038bced640a3e), + (0x2ad778f0e75a3dcad7c0cc2215e554f3d6fe41eabd612c487ea2708d59fb2e7e, 0x0561e9268230b53ec9cac0fd7654b3edaa3851f624c62bdae39519ae17526c06), + (0x358a21858e7f0da213959badd192b12e7bd40f6b18f5617a7fbad1f142b53c41, 0x1cc665c7a95332ea3ecb79bc35c4d672837809470691ad6a96f2eca081ca9c98), + (0x28d6468db328f1d201b3b7ca36f3affddee9dd0043d8868e34f1839742ac3190, 0x2f38eba3a82748cc28e46c1e20b7d343fdac7ef726ed6de89f6484c6070204f1), + (0x21f27b52cd9a76e1dbbf572fbfc0262007015777b68bda954f3c9db60ebb27f9, 0x0dbbf8f04e8476544a853e54093689d59935de9194eef24a0ee04d6faef9423f), + (0x0253a69e81add6bc1c2fe14bd90dab3e3c2603747dd3760c9dd1e341d96a79ed, 0x15cbe812a45a46512cc8ed493250f75a9dcaaee4be0d3bdaee8b43d74c50481f), + (0x19eb8760e7d0e6ae6d28d65627d958661cdde4e58a0aeb55a6b7017bcf723002, 0x064575794bf9bfdbc50e94b8afbbd2851ae4e12ff2809777d28fe71c235727d9), + (0x0e5c408b5224841cb4f75aec5cdb7bc95c150bbe858dbde8dbac9f72e5392462, 0x01030c69ac5fc7dd63e4e0bb1718d26f51b79dccc81e0b172e98c26e59145414), + (0x12437cb05ecff24131b52b5a55f6f143d8437c28c9d7c31eb06cfa093972a64b, 0x06e1a5e39566b4ce097a6c7dace6dcb827e54dac7d64fa79d994fb1557717614), + (0x34636ff9de412da15f41a8a006abbe8f43a5cffc94e6c3deb02f98af4fb2b8c7, 0x0270f0c3fa8cc7338f20fbcd5ec4e62799e051e0c5938d9e8c41581de8da6165), + (0x218e047b1c0a3b92c59539b3f6d9c23d34ebeeb65ca0be98f5e0e9642bdf1085, 0x20c1117f40b375688a94ff5c5c0b70004e43c7c7cd492fe8055fea081ea5ca78), + (0x2478c8226d4ede1c203fa7455b5fe28f99d5a0cb8ccdb5be4b54d5edcce974c4, 0x1ce69b76f05daeae57cd3d452370439237da89f2ddc84f7b2e35703acbf99655), + (0x08383138ecc6f2fb5459043c7666ae3df7802f1f02392af44db6ba25cd7d2c56, 0x20957d7a3f00a8589f627c5f5e471f45a84fbcbdcde00dfc97b9a97f3f723202), (0x21d210b41675a1eae44cbd0f3fd27d69e30716c71873f6089cee61acacd403ab, 0x2275e97c7e84f68bfaa528a9d8be4e059f7abefd80d03fbfca774e8414a9b7c1), (0x0f9e7de28e0f650d99d99d95c0fcd39c9dac9db5aa1973319f66922d6eb9f7d5, 0x1ba644ecc18ad711ddd33af7f695f6834e9f35c93d47a6a5273dabbe800fc7e6), (0x0aab3ab73afac76277cd94a891de15e42ceb09f3a9865dab5c814bebfbb4453f, 0x27119fec3736d99abeeef1ad7b857db7e754e0c158780ed3dd0cdd4dc2453e10), From 0417e233c3a855e66c7c24e0181dbd32a1d7f711 Mon Sep 17 00:00:00 2001 From: therealyingtong Date: Fri, 19 Nov 2021 00:04:27 -0500 Subject: [PATCH 02/59] poseidon: Return CellValue from squeeze() --- src/circuit.rs | 6 ++---- src/circuit/gadget/poseidon.rs | 11 ++++------- src/circuit/gadget/poseidon/pow5t3.rs | 3 +-- 3 files changed, 7 insertions(+), 13 deletions(-) diff --git a/src/circuit.rs b/src/circuit.rs index d011293c..cd184d63 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -488,12 +488,10 @@ impl plonk::Circuit for Circuit { layouter.namespace(|| "Poseidon init"), ConstantLength::<2>, )?; - let poseidon_output = poseidon_hasher.hash( + poseidon_hasher.hash( layouter.namespace(|| "Poseidon hash (nk, rho_old)"), poseidon_message, - )?; - let poseidon_output: CellValue = poseidon_output.inner().into(); - poseidon_output + )? }; // Add hash output to psi. diff --git a/src/circuit/gadget/poseidon.rs b/src/circuit/gadget/poseidon.rs index aa62013c..0fe4b97a 100644 --- a/src/circuit/gadget/poseidon.rs +++ b/src/circuit/gadget/poseidon.rs @@ -20,7 +20,7 @@ pub trait PoseidonInstructions, const T: usize, Chip { /// Variable representing the word over which the Poseidon permutation operates. - type Word: Copy + fmt::Debug + From>; + type Word: Copy + fmt::Debug + From> + Into>; /// Applies the Poseidon permutation to the given state. fn permute( @@ -182,10 +182,7 @@ impl< } /// Squeezes an element from the sponge. - pub fn squeeze( - &mut self, - mut layouter: impl Layouter, - ) -> Result, Error> { + pub fn squeeze(&mut self, mut layouter: impl Layouter) -> Result, Error> { loop { match self.sponge { Sponge::Absorbing(ref input) => { @@ -200,7 +197,7 @@ impl< Sponge::Squeezing(ref mut output) => { for entry in output.iter_mut() { if let Some(inner) = entry.take() { - return Ok(Word { inner }); + return Ok(inner.into()); } } @@ -253,7 +250,7 @@ impl< mut self, mut layouter: impl Layouter, message: [CellValue; L], - ) -> Result, Error> { + ) -> Result, Error> { for (i, value) in array::IntoIter::new(message).enumerate() { self.duplex .absorb(layouter.namespace(|| format!("absorb_{}", i)), value)?; diff --git a/src/circuit/gadget/poseidon/pow5t3.rs b/src/circuit/gadget/poseidon/pow5t3.rs index 8050919e..2b9c139a 100644 --- a/src/circuit/gadget/poseidon/pow5t3.rs +++ b/src/circuit/gadget/poseidon/pow5t3.rs @@ -821,8 +821,7 @@ mod tests { 0, || self.output.ok_or(Error::SynthesisError), )?; - let word: StateWord<_> = output.inner; - region.constrain_equal(word.var, expected_var) + region.constrain_equal(output.cell(), expected_var) }, ) } From fe1bc97ab48ae4a879272e114fed67158cf0c158 Mon Sep 17 00:00:00 2001 From: therealyingtong Date: Tue, 2 Nov 2021 15:52:11 +0100 Subject: [PATCH 03/59] Generalise Pow5T3 chip to be generic over WIDTH, RATE. --- src/circuit.rs | 4 +- src/circuit/gadget.rs | 4 +- src/circuit/gadget/poseidon.rs | 4 +- .../gadget/poseidon/{pow5t3.rs => pow5.rs} | 424 +++++------ src/circuit_description | 714 +++++++++--------- 5 files changed, 562 insertions(+), 588 deletions(-) rename src/circuit/gadget/poseidon/{pow5t3.rs => pow5.rs} (67%) diff --git a/src/circuit.rs b/src/circuit.rs index cd184d63..7d1e050a 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -40,7 +40,7 @@ use gadget::{ chip::{EccChip, EccConfig}, FixedPoint, FixedPointBaseField, FixedPointShort, NonIdentityPoint, Point, }, - poseidon::{Hash as PoseidonHash, Pow5T3Chip as PoseidonChip, Pow5T3Config as PoseidonConfig}, + poseidon::{Hash as PoseidonHash, Pow5Chip as PoseidonChip, Pow5Config as PoseidonConfig}, sinsemilla::{ chip::{SinsemillaChip, SinsemillaConfig, SinsemillaHashDomains}, commit_ivk::CommitIvkConfig, @@ -82,7 +82,7 @@ pub struct Config { q_add: Selector, advices: [Column; 10], ecc_config: EccConfig, - poseidon_config: PoseidonConfig, + poseidon_config: PoseidonConfig, merkle_config_1: MerkleConfig, merkle_config_2: MerkleConfig, sinsemilla_config_1: SinsemillaConfig, diff --git a/src/circuit/gadget.rs b/src/circuit/gadget.rs index 52c7723e..b0d8b247 100644 --- a/src/circuit/gadget.rs +++ b/src/circuit/gadget.rs @@ -1,7 +1,7 @@ use pasta_curves::pallas; use ecc::chip::EccChip; -use poseidon::Pow5T3Chip as PoseidonChip; +use poseidon::Pow5Chip as PoseidonChip; use sinsemilla::{chip::SinsemillaChip, merkle::chip::MerkleChip}; pub(crate) mod ecc; @@ -30,7 +30,7 @@ impl super::Config { MerkleChip::construct(self.merkle_config_2.clone()) } - pub(super) fn poseidon_chip(&self) -> PoseidonChip { + pub(super) fn poseidon_chip(&self) -> PoseidonChip { PoseidonChip::construct(self.poseidon_config.clone()) } } diff --git a/src/circuit/gadget/poseidon.rs b/src/circuit/gadget/poseidon.rs index 0fe4b97a..8a891ccf 100644 --- a/src/circuit/gadget/poseidon.rs +++ b/src/circuit/gadget/poseidon.rs @@ -9,8 +9,8 @@ use halo2::{ plonk::Error, }; -mod pow5t3; -pub use pow5t3::{Pow5T3Chip, Pow5T3Config, StateWord}; +mod pow5; +pub use pow5::{Pow5Chip, Pow5Config, StateWord}; use crate::circuit::gadget::utilities::CellValue; use crate::primitives::poseidon::{ConstantLength, Domain, Spec, Sponge, SpongeState, State}; diff --git a/src/circuit/gadget/poseidon/pow5t3.rs b/src/circuit/gadget/poseidon/pow5.rs similarity index 67% rename from src/circuit/gadget/poseidon/pow5t3.rs rename to src/circuit/gadget/poseidon/pow5.rs index 2b9c139a..64aa1b37 100644 --- a/src/circuit/gadget/poseidon/pow5t3.rs +++ b/src/circuit/gadget/poseidon/pow5.rs @@ -1,3 +1,4 @@ +use std::convert::TryInto; use std::iter; use halo2::{ @@ -11,11 +12,9 @@ use super::{PoseidonDuplexInstructions, PoseidonInstructions}; use crate::circuit::gadget::utilities::{CellValue, Var}; use crate::primitives::poseidon::{Domain, Mds, Spec, SpongeState, State}; -const WIDTH: usize = 3; - -/// Configuration for an [`Pow5T3Chip`]. +/// Configuration for a [`Pow5Chip`]. #[derive(Clone, Debug)] -pub struct Pow5T3Config { +pub struct Pow5Config { pub(in crate::circuit) state: [Column; WIDTH], partial_sbox: Column, rc_a: [Column; WIDTH], @@ -34,11 +33,11 @@ pub struct Pow5T3Config { /// A Poseidon chip using an $x^5$ S-Box, with a width of 3, suitable for a 2:1 reduction. #[derive(Debug)] -pub struct Pow5T3Chip { - config: Pow5T3Config, +pub struct Pow5Chip { + config: Pow5Config, } -impl Pow5T3Chip { +impl Pow5Chip { /// Configures this chip for use in a circuit. /// /// # Side-effects @@ -48,14 +47,15 @@ impl Pow5T3Chip { // TODO: Does the rate need to be hard-coded here, or only the width? It probably // needs to be known wherever we implement the hashing gadget, but it isn't strictly // necessary for the permutation. - pub fn configure>( + pub fn configure>( meta: &mut ConstraintSystem, spec: S, state: [Column; WIDTH], partial_sbox: Column, rc_a: [Column; WIDTH], rc_b: [Column; WIDTH], - ) -> Pow5T3Config { + ) -> Pow5Config { + assert_eq!(RATE, WIDTH - 1); // Generate constants for the Poseidon permutation. // This gadget requires R_F and R_P to be even. assert!(S::full_rounds() & 1 == 0); @@ -87,123 +87,96 @@ impl Pow5T3Chip { }; meta.create_gate("full round", |meta| { - let cur_0 = meta.query_advice(state[0], Rotation::cur()); - let cur_1 = meta.query_advice(state[1], Rotation::cur()); - let cur_2 = meta.query_advice(state[2], Rotation::cur()); - let next = [ - meta.query_advice(state[0], Rotation::next()), - meta.query_advice(state[1], Rotation::next()), - meta.query_advice(state[2], Rotation::next()), - ]; - - let rc_0 = meta.query_fixed(rc_a[0], Rotation::cur()); - let rc_1 = meta.query_fixed(rc_a[1], Rotation::cur()); - let rc_2 = meta.query_fixed(rc_a[2], Rotation::cur()); - let s_full = meta.query_selector(s_full); - let full_round = |next_idx: usize| { - s_full.clone() - * (pow_5(cur_0.clone() + rc_0.clone()) * m_reg[next_idx][0] - + pow_5(cur_1.clone() + rc_1.clone()) * m_reg[next_idx][1] - + pow_5(cur_2.clone() + rc_2.clone()) * m_reg[next_idx][2] - - next[next_idx].clone()) - }; - - vec![ - ("state[0]", full_round(0)), - ("state[1]", full_round(1)), - ("state[2]", full_round(2)), - ] + (0..WIDTH) + .map(|next_idx| { + let state_next = meta.query_advice(state[next_idx], Rotation::next()); + let expr = (0..WIDTH).fold(-state_next, |acc, idx| { + let state_cur = meta.query_advice(state[idx], Rotation::cur()); + let rc_a = meta.query_fixed(rc_a[idx], Rotation::cur()); + acc + pow_5(state_cur + rc_a) * m_reg[next_idx][idx] + }); + s_full.clone() * expr + }) + .collect::>() }); meta.create_gate("partial rounds", |meta| { let cur_0 = meta.query_advice(state[0], Rotation::cur()); - let cur_1 = meta.query_advice(state[1], Rotation::cur()); - let cur_2 = meta.query_advice(state[2], Rotation::cur()); let mid_0 = meta.query_advice(partial_sbox, Rotation::cur()); - let next_0 = meta.query_advice(state[0], Rotation::next()); - let next_1 = meta.query_advice(state[1], Rotation::next()); - let next_2 = meta.query_advice(state[2], Rotation::next()); let rc_a0 = meta.query_fixed(rc_a[0], Rotation::cur()); - let rc_a1 = meta.query_fixed(rc_a[1], Rotation::cur()); - let rc_a2 = meta.query_fixed(rc_a[2], Rotation::cur()); let rc_b0 = meta.query_fixed(rc_b[0], Rotation::cur()); - let rc_b1 = meta.query_fixed(rc_b[1], Rotation::cur()); - let rc_b2 = meta.query_fixed(rc_b[2], Rotation::cur()); let s_partial = meta.query_selector(s_partial); - let partial_round_linear = |idx: usize, rc_b: Expression| { - s_partial.clone() - * (mid_0.clone() * m_reg[idx][0] - + (cur_1.clone() + rc_a1.clone()) * m_reg[idx][1] - + (cur_2.clone() + rc_a2.clone()) * m_reg[idx][2] - + rc_b - - (next_0.clone() * m_inv[idx][0] - + next_1.clone() * m_inv[idx][1] - + next_2.clone() * m_inv[idx][2])) + use halo2::plonk::VirtualCells; + let mid = |idx: usize, meta: &mut VirtualCells| { + let mid = mid_0.clone() * m_reg[idx][0]; + (1..WIDTH).fold(mid, |acc, cur_idx| { + let cur = meta.query_advice(state[cur_idx], Rotation::cur()); + let rc_a = meta.query_fixed(rc_a[cur_idx], Rotation::cur()); + acc + (cur + rc_a) * m_reg[idx][cur_idx] + }) }; - vec![ - ( - "state[0] round a", + let next = |idx: usize, meta: &mut VirtualCells| { + let next_0 = meta.query_advice(state[0], Rotation::next()); + let next_0 = next_0 * m_inv[idx][0]; + (1..WIDTH).fold(next_0, |acc, next_idx| { + let next = meta.query_advice(state[next_idx], Rotation::next()); + acc + next * m_inv[idx][next_idx] + }) + }; + + let partial_round_linear = |idx: usize, meta: &mut VirtualCells| { + let expr = { + let rc_b = meta.query_fixed(rc_b[idx], Rotation::cur()); + mid(idx, meta) + rc_b - next(idx, meta) + }; + s_partial.clone() * expr + }; + + std::iter::empty() + // state[0] round a + .chain(Some( s_partial.clone() * (pow_5(cur_0 + rc_a0) - mid_0.clone()), - ), - ( - "state[0] round b", - s_partial.clone() - * (pow_5( - mid_0.clone() * m_reg[0][0] - + (cur_1.clone() + rc_a1.clone()) * m_reg[0][1] - + (cur_2.clone() + rc_a2.clone()) * m_reg[0][2] - + rc_b0, - ) - (next_0.clone() * m_inv[0][0] - + next_1.clone() * m_inv[0][1] - + next_2.clone() * m_inv[0][2])), - ), - ("state[1]", partial_round_linear(1, rc_b1)), - ("state[2]", partial_round_linear(2, rc_b2)), - ] + )) + // state[0] round b + .chain(Some( + s_partial.clone() * (pow_5(mid(0, meta) + rc_b0) - next(0, meta)), + )) + .chain((1..WIDTH).map(|idx| partial_round_linear(idx, meta))) + .collect::>() }); meta.create_gate("pad-and-add", |meta| { - let initial_state_0 = meta.query_advice(state[0], Rotation::prev()); - let initial_state_1 = meta.query_advice(state[1], Rotation::prev()); - let initial_state_2 = meta.query_advice(state[2], Rotation::prev()); - let input_0 = meta.query_advice(state[0], Rotation::cur()); - let input_1 = meta.query_advice(state[1], Rotation::cur()); - let output_state_0 = meta.query_advice(state[0], Rotation::next()); - let output_state_1 = meta.query_advice(state[1], Rotation::next()); - let output_state_2 = meta.query_advice(state[2], Rotation::next()); + let initial_state_rate = meta.query_advice(state[RATE], Rotation::prev()); + let output_state_rate = meta.query_advice(state[RATE], Rotation::next()); let s_pad_and_add = meta.query_selector(s_pad_and_add); - let pad_and_add = |initial_state, input, output_state| { + let pad_and_add = |idx: usize| { + let initial_state = meta.query_advice(state[idx], Rotation::prev()); + let input = meta.query_advice(state[idx], Rotation::cur()); + let output_state = meta.query_advice(state[idx], Rotation::next()); + // We pad the input by storing the required padding in fixed columns and // then constraining the corresponding input columns to be equal to it. s_pad_and_add.clone() * (initial_state + input - output_state) }; - vec![ - ( - "state[0]", - pad_and_add(initial_state_0, input_0, output_state_0), - ), - ( - "state[1]", - pad_and_add(initial_state_1, input_1, output_state_1), - ), + (0..RATE) + .map(pad_and_add) // The capacity element is never altered by the input. - ( - "state[2]", - s_pad_and_add * (initial_state_2 - output_state_2), - ), - ] + .chain(Some( + s_pad_and_add.clone() * (initial_state_rate - output_state_rate), + )) + .collect::>() }); - Pow5T3Config { + Pow5Config { state, partial_sbox, rc_a, @@ -220,13 +193,13 @@ impl Pow5T3Chip { } } - pub fn construct(config: Pow5T3Config) -> Self { - Pow5T3Chip { config } + pub fn construct(config: Pow5Config) -> Self { + Pow5Chip { config } } } -impl Chip for Pow5T3Chip { - type Config = Pow5T3Config; +impl Chip for Pow5Chip { + type Config = Pow5Config; type Loaded = (); fn config(&self) -> &Self::Config { @@ -238,7 +211,9 @@ impl Chip for Pow5T3Chip { } } -impl> PoseidonInstructions for Pow5T3Chip { +impl, const WIDTH: usize, const RATE: usize> + PoseidonInstructions for Pow5Chip +{ type Word = StateWord; fn permute( @@ -252,7 +227,7 @@ impl> PoseidonInstructions for || "permute state", |mut region| { // Load the initial state into this region. - let state = Pow5T3State::load(&mut region, config, initial_state)?; + let state = Pow5State::load(&mut region, config, initial_state)?; let state = (0..config.half_full_rounds).fold(Ok(state), |res, r| { res.and_then(|state| state.full_round(&mut region, config, r, r)) @@ -286,46 +261,52 @@ impl> PoseidonInstructions for } } -impl> PoseidonDuplexInstructions - for Pow5T3Chip +impl, const WIDTH: usize, const RATE: usize> + PoseidonDuplexInstructions for Pow5Chip { fn initial_state( &self, layouter: &mut impl Layouter, - domain: &impl Domain, + domain: &impl Domain, ) -> Result, Error> { let config = self.config(); - layouter.assign_region( + let state = layouter.assign_region( || format!("initial state for domain {:?}", domain), |mut region| { - let mut load_state_word = |i: usize, value: F| { + let mut state = Vec::with_capacity(WIDTH); + let mut load_state_word = |i: usize, value: F| -> Result<_, Error> { let var = region.assign_advice_from_constant( || format!("state_{}", i), config.state[i], 0, value, )?; - Ok(StateWord { + state.push(StateWord { var, value: Some(value), - }) + }); + + Ok(()) }; - Ok([ - load_state_word(0, F::zero())?, - load_state_word(1, F::zero())?, - load_state_word(2, domain.initial_capacity_element())?, - ]) + for i in 0..RATE { + load_state_word(i, F::zero())?; + } + load_state_word(RATE, domain.initial_capacity_element())?; + + Ok(state) }, - ) + )?; + + Ok(state.try_into().unwrap()) } fn pad_and_add( &self, layouter: &mut impl Layouter, - domain: &impl Domain, + domain: &impl Domain, initial_state: &State, - input: &SpongeState, + input: &SpongeState, ) -> Result, Error> { let config = self.config(); layouter.assign_region( @@ -334,7 +315,7 @@ impl> PoseidonDuplexInstructions> PoseidonDuplexInstructions, Error> = + (0..WIDTH).map(load_state_word).collect(); + let initial_state = initial_state?; let padding_values = domain.padding(); // Load the input and padding into this region. - let mut load_input_word = |i: usize| { + let load_input_word = |i: usize| { let (constraint_var, value) = match (input[i], padding_values[i]) { (Some(word), None) => (word.var, word.value), (None, Some(padding_value)) => { @@ -378,10 +357,11 @@ impl> PoseidonDuplexInstructions, Error> = (0..RATE).map(load_input_word).collect(); + let input = input?; // Constrain the output. - let mut constrain_output_word = |i: usize| { + let constrain_output_word = |i: usize| { let value = initial_state[i].value.and_then(|initial_word| { input .get(i) @@ -399,17 +379,19 @@ impl> PoseidonDuplexInstructions, Error> = (0..WIDTH).map(constrain_output_word).collect(); + output.map(|output| output.try_into().unwrap()) }, ) } - fn get_output(state: &State) -> SpongeState { - [Some(state[0]), Some(state[1])] + fn get_output(state: &State) -> SpongeState { + state[..RATE] + .iter() + .map(|word| Some(*word)) + .collect::>() + .try_into() + .unwrap() } } @@ -438,83 +420,73 @@ impl From> for StateWord { } #[derive(Debug)] -struct Pow5T3State([StateWord; WIDTH]); +struct Pow5State([StateWord; WIDTH]); -impl Pow5T3State { - fn full_round( +impl Pow5State { + fn full_round( self, region: &mut Region, - config: &Pow5T3Config, + config: &Pow5Config, round: usize, offset: usize, ) -> Result { Self::round(region, config, round, offset, config.s_full, |_| { - let q_0 = self.0[0] - .value - .map(|v| v + config.round_constants[round][0]); - let q_1 = self.0[1] - .value - .map(|v| v + config.round_constants[round][1]); - let q_2 = self.0[2] - .value - .map(|v| v + config.round_constants[round][2]); - - let r_0 = q_0.map(|v| v.pow(&config.alpha)); - let r_1 = q_1.map(|v| v.pow(&config.alpha)); - let r_2 = q_2.map(|v| v.pow(&config.alpha)); - + let q = self + .0 + .iter() + .enumerate() + .map(|(idx, word)| word.value.map(|v| v + config.round_constants[round][idx])); + let r: Option> = q.map(|q| q.map(|q| q.pow(&config.alpha))).collect(); let m = &config.m_reg; - let r = r_0.and_then(|r_0| r_1.and_then(|r_1| r_2.map(|r_2| [r_0, r_1, r_2]))); + let state = m.iter().map(|m_i| { + r.as_ref().map(|r| { + r.iter() + .enumerate() + .fold(F::zero(), |acc, (j, r_j)| acc + m_i[j] * r_j) + }) + }); - Ok(( - round + 1, - [ - r.map(|r| m[0][0] * r[0] + m[0][1] * r[1] + m[0][2] * r[2]), - r.map(|r| m[1][0] * r[0] + m[1][1] * r[1] + m[1][2] * r[2]), - r.map(|r| m[2][0] * r[0] + m[2][1] * r[1] + m[2][2] * r[2]), - ], - )) + Ok((round + 1, state.collect::>().try_into().unwrap())) }) } - fn partial_round( + fn partial_round( self, region: &mut Region, - config: &Pow5T3Config, + config: &Pow5Config, round: usize, offset: usize, ) -> Result { Self::round(region, config, round, offset, config.s_partial, |region| { let m = &config.m_reg; + let p: Option> = self.0.iter().map(|word| word.value).collect(); - let p = self.0[0].value.and_then(|p_0| { - self.0[1] - .value - .and_then(|p_1| self.0[2].value.map(|p_2| [p_0, p_1, p_2])) - }); - - let r = p.map(|p| { - [ - (p[0] + config.round_constants[round][0]).pow(&config.alpha), - p[1] + config.round_constants[round][1], - p[2] + config.round_constants[round][2], - ] + let r: Option> = p.map(|p| { + let r_0 = (p[0] + config.round_constants[round][0]).pow(&config.alpha); + let r_i = p[1..] + .iter() + .enumerate() + .map(|(i, p_i)| *p_i + config.round_constants[round][i + 1]); + std::iter::empty().chain(Some(r_0)).chain(r_i).collect() }); region.assign_advice( || format!("round_{} partial_sbox", round), config.partial_sbox, offset, - || r.map(|r| r[0]).ok_or(Error::SynthesisError), + || r.as_ref().map(|r| r[0]).ok_or(Error::SynthesisError), )?; - let p_mid = r.map(|r| { - [ - m[0][0] * r[0] + m[0][1] * r[1] + m[0][2] * r[2], - m[1][0] * r[0] + m[1][1] * r[1] + m[1][2] * r[2], - m[2][0] * r[0] + m[2][1] * r[1] + m[2][2] * r[2], - ] - }); + let p_mid: Option> = m + .iter() + .map(|m_i| { + r.as_ref().map(|r| { + r.iter() + .enumerate() + .fold(F::zero(), |acc, (j, r_j)| acc + m_i[j] * r_j) + }) + }) + .collect(); // Load the second round constants. let mut load_round_constant = |i: usize| { @@ -529,31 +501,36 @@ impl Pow5T3State { load_round_constant(i)?; } - let r_mid = p_mid.map(|p| { - [ - (p[0] + config.round_constants[round + 1][0]).pow(&config.alpha), - p[1] + config.round_constants[round + 1][1], - p[2] + config.round_constants[round + 1][2], - ] + let r_mid: Option> = p_mid.map(|p| { + let r_0 = (p[0] + config.round_constants[round + 1][0]).pow(&config.alpha); + let r_i = p[1..] + .iter() + .enumerate() + .map(|(i, p_i)| *p_i + config.round_constants[round + 1][i + 1]); + std::iter::empty().chain(Some(r_0)).chain(r_i).collect() }); - Ok(( - round + 2, - [ - r_mid.map(|r| m[0][0] * r[0] + m[0][1] * r[1] + m[0][2] * r[2]), - r_mid.map(|r| m[1][0] * r[0] + m[1][1] * r[1] + m[1][2] * r[2]), - r_mid.map(|r| m[2][0] * r[0] + m[2][1] * r[1] + m[2][2] * r[2]), - ], - )) + let state: Vec> = m + .iter() + .map(|m_i| { + r_mid.as_ref().map(|r| { + r.iter() + .enumerate() + .fold(F::zero(), |acc, (j, r_j)| acc + m_i[j] * r_j) + }) + }) + .collect(); + + Ok((round + 2, state.try_into().unwrap())) }) } - fn load( + fn load( region: &mut Region, - config: &Pow5T3Config, + config: &Pow5Config, initial_state: &State, WIDTH>, ) -> Result { - let mut load_state_word = |i: usize| { + let load_state_word = |i: usize| { let value = initial_state[i].value; let var = region.assign_advice( || format!("load state_{}", i), @@ -565,16 +542,13 @@ impl Pow5T3State { Ok(StateWord { var, value }) }; - Ok(Pow5T3State([ - load_state_word(0)?, - load_state_word(1)?, - load_state_word(2)?, - ])) + let state: Result, _> = (0..WIDTH).map(load_state_word).collect(); + state.map(|state| Pow5State(state.try_into().unwrap())) } - fn round( + fn round( region: &mut Region, - config: &Pow5T3Config, + config: &Pow5Config, round: usize, offset: usize, round_gate: Selector, @@ -599,7 +573,7 @@ impl Pow5T3State { // Compute the next round's state. let (next_round, next_state) = round_fn(region)?; - let mut next_state_word = |i: usize| { + let next_state_word = |i: usize| { let value = next_state[i]; let var = region.assign_advice( || format!("round_{} state_{}", next_round, i), @@ -610,11 +584,8 @@ impl Pow5T3State { Ok(StateWord { var, value }) }; - Ok(Pow5T3State([ - next_state_word(0)?, - next_state_word(1)?, - next_state_word(2)?, - ])) + let next_state: Result, _> = (0..WIDTH).map(next_state_word).collect(); + next_state.map(|next_state| Pow5State(next_state.try_into().unwrap())) } } @@ -630,7 +601,7 @@ mod tests { }; use pasta_curves::pallas; - use super::{PoseidonInstructions, Pow5T3Chip, Pow5T3Config, StateWord, WIDTH}; + use super::{PoseidonInstructions, Pow5Chip, Pow5Config, StateWord}; use crate::{ circuit::gadget::{ poseidon::Hash, @@ -639,17 +610,20 @@ mod tests { primitives::poseidon::{self, ConstantLength, P128Pow5T3 as OrchardNullifier, Spec}, }; + const WIDTH: usize = 3; + const RATE: usize = 2; + struct PermuteCircuit {} impl Circuit for PermuteCircuit { - type Config = Pow5T3Config; + type Config = Pow5Config; type FloorPlanner = SimpleFloorPlanner; fn without_witnesses(&self) -> Self { PermuteCircuit {} } - fn configure(meta: &mut ConstraintSystem) -> Pow5T3Config { + fn configure(meta: &mut ConstraintSystem) -> Pow5Config { let state = [ meta.advice_column(), meta.advice_column(), @@ -668,12 +642,12 @@ mod tests { meta.fixed_column(), ]; - Pow5T3Chip::configure(meta, OrchardNullifier, state, partial_sbox, rc_a, rc_b) + Pow5Chip::configure(meta, OrchardNullifier, state, partial_sbox, rc_a, rc_b) } fn synthesize( &self, - config: Pow5T3Config, + config: Pow5Config, mut layouter: impl Layouter, ) -> Result<(), Error> { let initial_state = layouter.assign_region( @@ -694,8 +668,8 @@ mod tests { }, )?; - let chip = Pow5T3Chip::construct(config.clone()); - let final_state = as PoseidonInstructions< + let chip = Pow5Chip::construct(config.clone()); + let final_state = as PoseidonInstructions< Fp, OrchardNullifier, WIDTH, @@ -705,7 +679,7 @@ mod tests { // For the purpose of this test, compute the real final state inline. let mut expected_final_state = [Fp::zero(), Fp::one(), Fp::from_u64(2)]; let (round_constants, mds, _) = OrchardNullifier.constants(); - poseidon::permute::<_, OrchardNullifier, WIDTH, 2>( + poseidon::permute::<_, OrchardNullifier, WIDTH, RATE>( &mut expected_final_state, &mds, &round_constants, @@ -749,14 +723,14 @@ mod tests { } impl Circuit for HashCircuit { - type Config = Pow5T3Config; + type Config = Pow5Config; type FloorPlanner = SimpleFloorPlanner; fn without_witnesses(&self) -> Self { Self::default() } - fn configure(meta: &mut ConstraintSystem) -> Pow5T3Config { + fn configure(meta: &mut ConstraintSystem) -> Pow5Config { let state = [ meta.advice_column(), meta.advice_column(), @@ -777,15 +751,15 @@ mod tests { meta.enable_constant(rc_b[0]); - Pow5T3Chip::configure(meta, OrchardNullifier, state, partial_sbox, rc_a, rc_b) + Pow5Chip::configure(meta, OrchardNullifier, state, partial_sbox, rc_a, rc_b) } fn synthesize( &self, - config: Pow5T3Config, + config: Pow5Config, mut layouter: impl Layouter, ) -> Result<(), Error> { - let chip = Pow5T3Chip::construct(config.clone()); + let chip = Pow5Chip::construct(config.clone()); let message = layouter.assign_region( || "load message", diff --git a/src/circuit_description b/src/circuit_description index 552652ad..2ac02557 100644 --- a/src/circuit_description +++ b/src/circuit_description @@ -10831,6 +10831,15 @@ PinnedVerificationKey { Sum( Sum( Sum( + Negated( + Advice { + query_index: 22, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + ), Scaled( Product( Product( @@ -10922,97 +10931,6 @@ PinnedVerificationKey { ), 0x0ab5e5b874a68de7b3d59fbdc8c9ead497d7a0ab23850b56323f2486d7e11b63, ), - Scaled( - Product( - Product( - Product( - Sum( - Advice { - query_index: 7, - column_index: 7, - rotation: Rotation( - 0, - ), - }, - Fixed { - query_index: 5, - column_index: 6, - rotation: Rotation( - 0, - ), - }, - ), - Sum( - Advice { - query_index: 7, - column_index: 7, - rotation: Rotation( - 0, - ), - }, - Fixed { - query_index: 5, - column_index: 6, - rotation: Rotation( - 0, - ), - }, - ), - ), - Product( - Sum( - Advice { - query_index: 7, - column_index: 7, - rotation: Rotation( - 0, - ), - }, - Fixed { - query_index: 5, - column_index: 6, - rotation: Rotation( - 0, - ), - }, - ), - Sum( - Advice { - query_index: 7, - column_index: 7, - rotation: Rotation( - 0, - ), - }, - Fixed { - query_index: 5, - column_index: 6, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Advice { - query_index: 7, - column_index: 7, - rotation: Rotation( - 0, - ), - }, - Fixed { - query_index: 5, - column_index: 6, - rotation: Rotation( - 0, - ), - }, - ), - ), - 0x31916628e58a5abb293f0f0d886c7954240d4a7cbf7357368eca5596e996ab5e, - ), ), Scaled( Product( @@ -11020,15 +10938,15 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 8, - column_index: 8, + query_index: 7, + column_index: 7, rotation: Rotation( 0, ), }, Fixed { - query_index: 6, - column_index: 7, + query_index: 5, + column_index: 6, rotation: Rotation( 0, ), @@ -11036,15 +10954,15 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 8, - column_index: 8, + query_index: 7, + column_index: 7, rotation: Rotation( 0, ), }, Fixed { - query_index: 6, - column_index: 7, + query_index: 5, + column_index: 6, rotation: Rotation( 0, ), @@ -11054,15 +10972,15 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 8, - column_index: 8, + query_index: 7, + column_index: 7, rotation: Rotation( 0, ), }, Fixed { - query_index: 6, - column_index: 7, + query_index: 5, + column_index: 6, rotation: Rotation( 0, ), @@ -11070,15 +10988,15 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 8, - column_index: 8, + query_index: 7, + column_index: 7, rotation: Rotation( 0, ), }, Fixed { - query_index: 6, - column_index: 7, + query_index: 5, + column_index: 6, rotation: Rotation( 0, ), @@ -11088,32 +11006,114 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 8, - column_index: 8, + query_index: 7, + column_index: 7, rotation: Rotation( 0, ), }, Fixed { - query_index: 6, - column_index: 7, + query_index: 5, + column_index: 6, rotation: Rotation( 0, ), }, ), ), - 0x07c045d5f5e9e5a6d803952bbb364fdfa0a3b71a5fb1573519d1cf25d8e8345d, + 0x31916628e58a5abb293f0f0d886c7954240d4a7cbf7357368eca5596e996ab5e, ), ), - Negated( - Advice { - query_index: 22, - column_index: 6, - rotation: Rotation( - 1, + Scaled( + Product( + Product( + Product( + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), ), - }, + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + 0x07c045d5f5e9e5a6d803952bbb364fdfa0a3b71a5fb1573519d1cf25d8e8345d, ), ), ), @@ -11176,6 +11176,15 @@ PinnedVerificationKey { Sum( Sum( Sum( + Negated( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), Scaled( Product( Product( @@ -11267,97 +11276,6 @@ PinnedVerificationKey { ), 0x233162630ebf9ed7f8e24f66822c2d9f3a0a464048bd770ad049cdc8d085167c, ), - Scaled( - Product( - Product( - Product( - Sum( - Advice { - query_index: 7, - column_index: 7, - rotation: Rotation( - 0, - ), - }, - Fixed { - query_index: 5, - column_index: 6, - rotation: Rotation( - 0, - ), - }, - ), - Sum( - Advice { - query_index: 7, - column_index: 7, - rotation: Rotation( - 0, - ), - }, - Fixed { - query_index: 5, - column_index: 6, - rotation: Rotation( - 0, - ), - }, - ), - ), - Product( - Sum( - Advice { - query_index: 7, - column_index: 7, - rotation: Rotation( - 0, - ), - }, - Fixed { - query_index: 5, - column_index: 6, - rotation: Rotation( - 0, - ), - }, - ), - Sum( - Advice { - query_index: 7, - column_index: 7, - rotation: Rotation( - 0, - ), - }, - Fixed { - query_index: 5, - column_index: 6, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Advice { - query_index: 7, - column_index: 7, - rotation: Rotation( - 0, - ), - }, - Fixed { - query_index: 5, - column_index: 6, - rotation: Rotation( - 0, - ), - }, - ), - ), - 0x25cae2599892a8b0b36664548d60957d78f8365c85bbab07402270113e047a2e, - ), ), Scaled( Product( @@ -11365,15 +11283,15 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 8, - column_index: 8, + query_index: 7, + column_index: 7, rotation: Rotation( 0, ), }, Fixed { - query_index: 6, - column_index: 7, + query_index: 5, + column_index: 6, rotation: Rotation( 0, ), @@ -11381,15 +11299,15 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 8, - column_index: 8, + query_index: 7, + column_index: 7, rotation: Rotation( 0, ), }, Fixed { - query_index: 6, - column_index: 7, + query_index: 5, + column_index: 6, rotation: Rotation( 0, ), @@ -11399,15 +11317,15 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 8, - column_index: 8, + query_index: 7, + column_index: 7, rotation: Rotation( 0, ), }, Fixed { - query_index: 6, - column_index: 7, + query_index: 5, + column_index: 6, rotation: Rotation( 0, ), @@ -11415,15 +11333,15 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 8, - column_index: 8, + query_index: 7, + column_index: 7, rotation: Rotation( 0, ), }, Fixed { - query_index: 6, - column_index: 7, + query_index: 5, + column_index: 6, rotation: Rotation( 0, ), @@ -11433,32 +11351,114 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 8, - column_index: 8, + query_index: 7, + column_index: 7, rotation: Rotation( 0, ), }, Fixed { - query_index: 6, - column_index: 7, + query_index: 5, + column_index: 6, rotation: Rotation( 0, ), }, ), ), - 0x22f5b5e1e6081c9774938717989a19579aad3d8262efd83ff84d806f685f747a, + 0x25cae2599892a8b0b36664548d60957d78f8365c85bbab07402270113e047a2e, ), ), - Negated( - Advice { - query_index: 18, - column_index: 7, - rotation: Rotation( - 1, + Scaled( + Product( + Product( + Product( + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), ), - }, + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + 0x22f5b5e1e6081c9774938717989a19579aad3d8262efd83ff84d806f685f747a, ), ), ), @@ -11521,6 +11521,15 @@ PinnedVerificationKey { Sum( Sum( Sum( + Negated( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), Scaled( Product( Product( @@ -11612,97 +11621,6 @@ PinnedVerificationKey { ), 0x2e29dd59c64b1037f333aa91c383346421680eabc56bc15dfee7a9944f84dbe4, ), - Scaled( - Product( - Product( - Product( - Sum( - Advice { - query_index: 7, - column_index: 7, - rotation: Rotation( - 0, - ), - }, - Fixed { - query_index: 5, - column_index: 6, - rotation: Rotation( - 0, - ), - }, - ), - Sum( - Advice { - query_index: 7, - column_index: 7, - rotation: Rotation( - 0, - ), - }, - Fixed { - query_index: 5, - column_index: 6, - rotation: Rotation( - 0, - ), - }, - ), - ), - Product( - Sum( - Advice { - query_index: 7, - column_index: 7, - rotation: Rotation( - 0, - ), - }, - Fixed { - query_index: 5, - column_index: 6, - rotation: Rotation( - 0, - ), - }, - ), - Sum( - Advice { - query_index: 7, - column_index: 7, - rotation: Rotation( - 0, - ), - }, - Fixed { - query_index: 5, - column_index: 6, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Advice { - query_index: 7, - column_index: 7, - rotation: Rotation( - 0, - ), - }, - Fixed { - query_index: 5, - column_index: 6, - rotation: Rotation( - 0, - ), - }, - ), - ), - 0x1d1aab4ec1cd678892d15e7dceef1665cbeaf48b3a0624c3c771effa43263664, - ), ), Scaled( Product( @@ -11710,15 +11628,15 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 8, - column_index: 8, + query_index: 7, + column_index: 7, rotation: Rotation( 0, ), }, Fixed { - query_index: 6, - column_index: 7, + query_index: 5, + column_index: 6, rotation: Rotation( 0, ), @@ -11726,15 +11644,15 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 8, - column_index: 8, + query_index: 7, + column_index: 7, rotation: Rotation( 0, ), }, Fixed { - query_index: 6, - column_index: 7, + query_index: 5, + column_index: 6, rotation: Rotation( 0, ), @@ -11744,15 +11662,15 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 8, - column_index: 8, + query_index: 7, + column_index: 7, rotation: Rotation( 0, ), }, Fixed { - query_index: 6, - column_index: 7, + query_index: 5, + column_index: 6, rotation: Rotation( 0, ), @@ -11760,15 +11678,15 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 8, - column_index: 8, + query_index: 7, + column_index: 7, rotation: Rotation( 0, ), }, Fixed { - query_index: 6, - column_index: 7, + query_index: 5, + column_index: 6, rotation: Rotation( 0, ), @@ -11778,32 +11696,114 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 8, - column_index: 8, + query_index: 7, + column_index: 7, rotation: Rotation( 0, ), }, Fixed { - query_index: 6, - column_index: 7, + query_index: 5, + column_index: 6, rotation: Rotation( 0, ), }, ), ), - 0x3bf763086a18936451e0cbead65516b975872c39b59a31f615639415f6e85ef1, + 0x1d1aab4ec1cd678892d15e7dceef1665cbeaf48b3a0624c3c771effa43263664, ), ), - Negated( - Advice { - query_index: 19, - column_index: 8, - rotation: Rotation( - 1, + Scaled( + Product( + Product( + Product( + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), ), - }, + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + 0x3bf763086a18936451e0cbead65516b975872c39b59a31f615639415f6e85ef1, ), ), ), From 79123629dac71de8156e20a90bc49efacf2b0606 Mon Sep 17 00:00:00 2001 From: ying tong Date: Tue, 23 Nov 2021 15:29:56 -0500 Subject: [PATCH 04/59] Docfixes and minor refactors. Co-authored-by: str4d --- src/circuit/gadget/poseidon/pow5.rs | 30 ++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/src/circuit/gadget/poseidon/pow5.rs b/src/circuit/gadget/poseidon/pow5.rs index 64aa1b37..69eabf7a 100644 --- a/src/circuit/gadget/poseidon/pow5.rs +++ b/src/circuit/gadget/poseidon/pow5.rs @@ -31,7 +31,10 @@ pub struct Pow5Config { m_inv: Mds, } -/// A Poseidon chip using an $x^5$ S-Box, with a width of 3, suitable for a 2:1 reduction. +/// A Poseidon chip using an $x^5$ S-Box. +/// +/// The chip is implemented using a single round per row for full rounds, and two rounds +/// per row for partial rounds. #[derive(Debug)] pub struct Pow5Chip { config: Pow5Config, @@ -122,12 +125,13 @@ impl Pow5Chip| { - let next_0 = meta.query_advice(state[0], Rotation::next()); - let next_0 = next_0 * m_inv[idx][0]; - (1..WIDTH).fold(next_0, |acc, next_idx| { - let next = meta.query_advice(state[next_idx], Rotation::next()); - acc + next * m_inv[idx][next_idx] - }) + (0..WIDTH) + .map(|next_idx| { + let next = meta.query_advice(state[next_idx], Rotation::next()); + next * m_inv[idx][next_idx] + }) + .reduce(|acc, next| acc + next) + .expect("WIDTH > 0") }; let partial_round_linear = |idx: usize, meta: &mut VirtualCells| { @@ -481,9 +485,9 @@ impl Pow5State { .iter() .map(|m_i| { r.as_ref().map(|r| { - r.iter() - .enumerate() - .fold(F::zero(), |acc, (j, r_j)| acc + m_i[j] * r_j) + m_i.iter() + .zip(r.iter()) + .fold(F::zero(), |acc, (m_ij, r_j)| acc + *m_ij * r_j) }) }) .collect(); @@ -514,9 +518,9 @@ impl Pow5State { .iter() .map(|m_i| { r_mid.as_ref().map(|r| { - r.iter() - .enumerate() - .fold(F::zero(), |acc, (j, r_j)| acc + m_i[j] * r_j) + m_i.iter() + .zip(r.iter()) + .fold(F::zero(), |acc, (m_ij, r_j)| acc + *m_ij * r_j) }) }) .collect(); From 9bb29018accd9e0ecc8b0944b8270231fb273694 Mon Sep 17 00:00:00 2001 From: therealyingtong Date: Tue, 23 Nov 2021 15:38:55 -0500 Subject: [PATCH 05/59] poseidon::pow5: Undo circuit change. Co-authored-by: str4d --- src/circuit/gadget/poseidon/pow5.rs | 15 +- src/circuit_description | 714 ++++++++++++++-------------- 2 files changed, 366 insertions(+), 363 deletions(-) diff --git a/src/circuit/gadget/poseidon/pow5.rs b/src/circuit/gadget/poseidon/pow5.rs index 69eabf7a..e6395f80 100644 --- a/src/circuit/gadget/poseidon/pow5.rs +++ b/src/circuit/gadget/poseidon/pow5.rs @@ -95,12 +95,15 @@ impl Pow5Chip 0"); + s_full.clone() * (expr - state_next) }) .collect::>() }); diff --git a/src/circuit_description b/src/circuit_description index 2ac02557..552652ad 100644 --- a/src/circuit_description +++ b/src/circuit_description @@ -10831,15 +10831,6 @@ PinnedVerificationKey { Sum( Sum( Sum( - Negated( - Advice { - query_index: 22, - column_index: 6, - rotation: Rotation( - 1, - ), - }, - ), Scaled( Product( Product( @@ -10931,6 +10922,97 @@ PinnedVerificationKey { ), 0x0ab5e5b874a68de7b3d59fbdc8c9ead497d7a0ab23850b56323f2486d7e11b63, ), + Scaled( + Product( + Product( + Product( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + 0x31916628e58a5abb293f0f0d886c7954240d4a7cbf7357368eca5596e996ab5e, + ), ), Scaled( Product( @@ -10938,15 +11020,15 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 7, - column_index: 7, + query_index: 8, + column_index: 8, rotation: Rotation( 0, ), }, Fixed { - query_index: 5, - column_index: 6, + query_index: 6, + column_index: 7, rotation: Rotation( 0, ), @@ -10954,15 +11036,15 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 7, - column_index: 7, + query_index: 8, + column_index: 8, rotation: Rotation( 0, ), }, Fixed { - query_index: 5, - column_index: 6, + query_index: 6, + column_index: 7, rotation: Rotation( 0, ), @@ -10972,15 +11054,15 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 7, - column_index: 7, + query_index: 8, + column_index: 8, rotation: Rotation( 0, ), }, Fixed { - query_index: 5, - column_index: 6, + query_index: 6, + column_index: 7, rotation: Rotation( 0, ), @@ -10988,15 +11070,15 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 7, - column_index: 7, + query_index: 8, + column_index: 8, rotation: Rotation( 0, ), }, Fixed { - query_index: 5, - column_index: 6, + query_index: 6, + column_index: 7, rotation: Rotation( 0, ), @@ -11006,114 +11088,32 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 7, - column_index: 7, + query_index: 8, + column_index: 8, rotation: Rotation( 0, ), }, Fixed { - query_index: 5, - column_index: 6, + query_index: 6, + column_index: 7, rotation: Rotation( 0, ), }, ), ), - 0x31916628e58a5abb293f0f0d886c7954240d4a7cbf7357368eca5596e996ab5e, + 0x07c045d5f5e9e5a6d803952bbb364fdfa0a3b71a5fb1573519d1cf25d8e8345d, ), ), - Scaled( - Product( - Product( - Product( - Sum( - Advice { - query_index: 8, - column_index: 8, - rotation: Rotation( - 0, - ), - }, - Fixed { - query_index: 6, - column_index: 7, - rotation: Rotation( - 0, - ), - }, - ), - Sum( - Advice { - query_index: 8, - column_index: 8, - rotation: Rotation( - 0, - ), - }, - Fixed { - query_index: 6, - column_index: 7, - rotation: Rotation( - 0, - ), - }, - ), - ), - Product( - Sum( - Advice { - query_index: 8, - column_index: 8, - rotation: Rotation( - 0, - ), - }, - Fixed { - query_index: 6, - column_index: 7, - rotation: Rotation( - 0, - ), - }, - ), - Sum( - Advice { - query_index: 8, - column_index: 8, - rotation: Rotation( - 0, - ), - }, - Fixed { - query_index: 6, - column_index: 7, - rotation: Rotation( - 0, - ), - }, - ), - ), + Negated( + Advice { + query_index: 22, + column_index: 6, + rotation: Rotation( + 1, ), - Sum( - Advice { - query_index: 8, - column_index: 8, - rotation: Rotation( - 0, - ), - }, - Fixed { - query_index: 6, - column_index: 7, - rotation: Rotation( - 0, - ), - }, - ), - ), - 0x07c045d5f5e9e5a6d803952bbb364fdfa0a3b71a5fb1573519d1cf25d8e8345d, + }, ), ), ), @@ -11176,15 +11176,6 @@ PinnedVerificationKey { Sum( Sum( Sum( - Negated( - Advice { - query_index: 18, - column_index: 7, - rotation: Rotation( - 1, - ), - }, - ), Scaled( Product( Product( @@ -11276,6 +11267,97 @@ PinnedVerificationKey { ), 0x233162630ebf9ed7f8e24f66822c2d9f3a0a464048bd770ad049cdc8d085167c, ), + Scaled( + Product( + Product( + Product( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + 0x25cae2599892a8b0b36664548d60957d78f8365c85bbab07402270113e047a2e, + ), ), Scaled( Product( @@ -11283,15 +11365,15 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 7, - column_index: 7, + query_index: 8, + column_index: 8, rotation: Rotation( 0, ), }, Fixed { - query_index: 5, - column_index: 6, + query_index: 6, + column_index: 7, rotation: Rotation( 0, ), @@ -11299,15 +11381,15 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 7, - column_index: 7, + query_index: 8, + column_index: 8, rotation: Rotation( 0, ), }, Fixed { - query_index: 5, - column_index: 6, + query_index: 6, + column_index: 7, rotation: Rotation( 0, ), @@ -11317,15 +11399,15 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 7, - column_index: 7, + query_index: 8, + column_index: 8, rotation: Rotation( 0, ), }, Fixed { - query_index: 5, - column_index: 6, + query_index: 6, + column_index: 7, rotation: Rotation( 0, ), @@ -11333,15 +11415,15 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 7, - column_index: 7, + query_index: 8, + column_index: 8, rotation: Rotation( 0, ), }, Fixed { - query_index: 5, - column_index: 6, + query_index: 6, + column_index: 7, rotation: Rotation( 0, ), @@ -11351,114 +11433,32 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 7, - column_index: 7, + query_index: 8, + column_index: 8, rotation: Rotation( 0, ), }, Fixed { - query_index: 5, - column_index: 6, + query_index: 6, + column_index: 7, rotation: Rotation( 0, ), }, ), ), - 0x25cae2599892a8b0b36664548d60957d78f8365c85bbab07402270113e047a2e, + 0x22f5b5e1e6081c9774938717989a19579aad3d8262efd83ff84d806f685f747a, ), ), - Scaled( - Product( - Product( - Product( - Sum( - Advice { - query_index: 8, - column_index: 8, - rotation: Rotation( - 0, - ), - }, - Fixed { - query_index: 6, - column_index: 7, - rotation: Rotation( - 0, - ), - }, - ), - Sum( - Advice { - query_index: 8, - column_index: 8, - rotation: Rotation( - 0, - ), - }, - Fixed { - query_index: 6, - column_index: 7, - rotation: Rotation( - 0, - ), - }, - ), - ), - Product( - Sum( - Advice { - query_index: 8, - column_index: 8, - rotation: Rotation( - 0, - ), - }, - Fixed { - query_index: 6, - column_index: 7, - rotation: Rotation( - 0, - ), - }, - ), - Sum( - Advice { - query_index: 8, - column_index: 8, - rotation: Rotation( - 0, - ), - }, - Fixed { - query_index: 6, - column_index: 7, - rotation: Rotation( - 0, - ), - }, - ), - ), + Negated( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, ), - Sum( - Advice { - query_index: 8, - column_index: 8, - rotation: Rotation( - 0, - ), - }, - Fixed { - query_index: 6, - column_index: 7, - rotation: Rotation( - 0, - ), - }, - ), - ), - 0x22f5b5e1e6081c9774938717989a19579aad3d8262efd83ff84d806f685f747a, + }, ), ), ), @@ -11521,15 +11521,6 @@ PinnedVerificationKey { Sum( Sum( Sum( - Negated( - Advice { - query_index: 19, - column_index: 8, - rotation: Rotation( - 1, - ), - }, - ), Scaled( Product( Product( @@ -11621,6 +11612,97 @@ PinnedVerificationKey { ), 0x2e29dd59c64b1037f333aa91c383346421680eabc56bc15dfee7a9944f84dbe4, ), + Scaled( + Product( + Product( + Product( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + 0x1d1aab4ec1cd678892d15e7dceef1665cbeaf48b3a0624c3c771effa43263664, + ), ), Scaled( Product( @@ -11628,15 +11710,15 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 7, - column_index: 7, + query_index: 8, + column_index: 8, rotation: Rotation( 0, ), }, Fixed { - query_index: 5, - column_index: 6, + query_index: 6, + column_index: 7, rotation: Rotation( 0, ), @@ -11644,15 +11726,15 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 7, - column_index: 7, + query_index: 8, + column_index: 8, rotation: Rotation( 0, ), }, Fixed { - query_index: 5, - column_index: 6, + query_index: 6, + column_index: 7, rotation: Rotation( 0, ), @@ -11662,15 +11744,15 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 7, - column_index: 7, + query_index: 8, + column_index: 8, rotation: Rotation( 0, ), }, Fixed { - query_index: 5, - column_index: 6, + query_index: 6, + column_index: 7, rotation: Rotation( 0, ), @@ -11678,15 +11760,15 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 7, - column_index: 7, + query_index: 8, + column_index: 8, rotation: Rotation( 0, ), }, Fixed { - query_index: 5, - column_index: 6, + query_index: 6, + column_index: 7, rotation: Rotation( 0, ), @@ -11696,114 +11778,32 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 7, - column_index: 7, + query_index: 8, + column_index: 8, rotation: Rotation( 0, ), }, Fixed { - query_index: 5, - column_index: 6, + query_index: 6, + column_index: 7, rotation: Rotation( 0, ), }, ), ), - 0x1d1aab4ec1cd678892d15e7dceef1665cbeaf48b3a0624c3c771effa43263664, + 0x3bf763086a18936451e0cbead65516b975872c39b59a31f615639415f6e85ef1, ), ), - Scaled( - Product( - Product( - Product( - Sum( - Advice { - query_index: 8, - column_index: 8, - rotation: Rotation( - 0, - ), - }, - Fixed { - query_index: 6, - column_index: 7, - rotation: Rotation( - 0, - ), - }, - ), - Sum( - Advice { - query_index: 8, - column_index: 8, - rotation: Rotation( - 0, - ), - }, - Fixed { - query_index: 6, - column_index: 7, - rotation: Rotation( - 0, - ), - }, - ), - ), - Product( - Sum( - Advice { - query_index: 8, - column_index: 8, - rotation: Rotation( - 0, - ), - }, - Fixed { - query_index: 6, - column_index: 7, - rotation: Rotation( - 0, - ), - }, - ), - Sum( - Advice { - query_index: 8, - column_index: 8, - rotation: Rotation( - 0, - ), - }, - Fixed { - query_index: 6, - column_index: 7, - rotation: Rotation( - 0, - ), - }, - ), - ), + Negated( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, ), - Sum( - Advice { - query_index: 8, - column_index: 8, - rotation: Rotation( - 0, - ), - }, - Fixed { - query_index: 6, - column_index: 7, - rotation: Rotation( - 0, - ), - }, - ), - ), - 0x3bf763086a18936451e0cbead65516b975872c39b59a31f615639415f6e85ef1, + }, ), ), ), From 99d03e0d258447a6da691f470fb424728c4932da Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 24 Nov 2021 00:21:44 +0000 Subject: [PATCH 06/59] Migrate to latest halo2 revision --- Cargo.toml | 1 + benches/circuit.rs | 2 +- src/circuit.rs | 4 +- src/circuit/gadget/ecc/chip/add.rs | 36 +++------- src/circuit/gadget/ecc/chip/add_incomplete.rs | 6 +- src/circuit/gadget/ecc/chip/mul.rs | 6 +- src/circuit/gadget/ecc/chip/mul/complete.rs | 4 +- src/circuit/gadget/ecc/chip/mul/incomplete.rs | 16 ++--- src/circuit/gadget/ecc/chip/mul/overflow.rs | 4 +- src/circuit/gadget/ecc/chip/mul_fixed.rs | 17 ++--- .../ecc/chip/mul_fixed/base_field_elem.rs | 4 +- .../gadget/ecc/chip/mul_fixed/full_width.rs | 2 +- .../gadget/ecc/chip/mul_fixed/short.rs | 68 +++++++++++++++++-- src/circuit/gadget/ecc/chip/witness_point.rs | 18 ++--- src/circuit/gadget/poseidon/pow5.rs | 22 +++--- src/circuit/gadget/sinsemilla/chip.rs | 2 +- .../gadget/sinsemilla/chip/hash_to_point.rs | 16 ++--- src/circuit/gadget/sinsemilla/commit_ivk.rs | 4 +- src/circuit/gadget/sinsemilla/note_commit.rs | 12 ++-- src/circuit/gadget/utilities.rs | 9 +-- src/circuit/gadget/utilities/cond_swap.rs | 8 +-- .../gadget/utilities/decompose_running_sum.rs | 4 +- .../gadget/utilities/lookup_range_check.rs | 8 +-- 23 files changed, 152 insertions(+), 121 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index fd3d9d72..d12d0b32 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -86,3 +86,4 @@ debug = true [patch.crates-io] zcash_note_encryption = { git = "https://github.com/zcash/librustzcash.git", rev = "35e75420657599fdc701cb45704878eb3fa2e59a" } incrementalmerkletree = { git = "https://github.com/zcash/incrementalmerkletree.git", rev = "b7bd6246122a6e9ace8edb51553fbf5228906cbb" } +halo2 = { git = "https://github.com/zcash/halo2.git", rev = "8bfc58b7c76ae83ba5a9ed7ecdfe0ddfd40ed571" } diff --git a/benches/circuit.rs b/benches/circuit.rs index 14c41982..0c013e6a 100644 --- a/benches/circuit.rs +++ b/benches/circuit.rs @@ -63,7 +63,7 @@ fn criterion_benchmark(c: &mut Criterion) { .unwrap() .apply_signatures(rng, [0; 32], &[]) .unwrap(); - assert_eq!(bundle.verify_proof(&vk), Ok(())); + assert!(bundle.verify_proof(&vk).is_ok()); group.bench_function(BenchmarkId::new("bundle", num_recipients), |b| { b.iter(|| bundle.authorization().proof().verify(&vk, &instances)); }); diff --git a/src/circuit.rs b/src/circuit.rs index 7d1e050a..f1b741dd 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -525,7 +525,7 @@ impl plonk::Circuit for Circuit { || "poseidon_hash(nk, rho_old) + psi_old", config.advices[6], 0, - || scalar_val.ok_or(plonk::Error::SynthesisError), + || scalar_val.ok_or(plonk::Error::Synthesis), )?; Ok(CellValue::new(cell, scalar_val)) }, @@ -1055,7 +1055,7 @@ mod tests { halo2::dev::CircuitLayout::default() .show_labels(false) .view_height(0..(1 << 11)) - .render(K as usize, &circuit, &root) + .render(K, &circuit, &root) .unwrap(); } } diff --git a/src/circuit/gadget/ecc/chip/add.rs b/src/circuit/gadget/ecc/chip/add.rs index 34520ed8..3fdf7732 100644 --- a/src/circuit/gadget/ecc/chip/add.rs +++ b/src/circuit/gadget/ecc/chip/add.rs @@ -1,9 +1,8 @@ use std::array; use super::{copy, CellValue, EccConfig, EccPoint, Var}; -use ff::Field; +use ff::{BatchInvert, Field}; use halo2::{ - arithmetic::BatchInvert, circuit::Region, plonk::{Advice, Column, ConstraintSystem, Error, Expression, Selector}, poly::Rotation, @@ -243,28 +242,13 @@ impl Config { }; // Assign α = inv0(x_q - x_p) - region.assign_advice( - || "α", - self.alpha, - offset, - || alpha.ok_or(Error::SynthesisError), - )?; + region.assign_advice(|| "α", self.alpha, offset, || alpha.ok_or(Error::Synthesis))?; // Assign β = inv0(x_p) - region.assign_advice( - || "β", - self.beta, - offset, - || beta.ok_or(Error::SynthesisError), - )?; + region.assign_advice(|| "β", self.beta, offset, || beta.ok_or(Error::Synthesis))?; // Assign γ = inv0(x_q) - region.assign_advice( - || "γ", - self.gamma, - offset, - || gamma.ok_or(Error::SynthesisError), - )?; + region.assign_advice(|| "γ", self.gamma, offset, || gamma.ok_or(Error::Synthesis))?; // Assign δ = inv0(y_q + y_p) if x_q = x_p, 0 otherwise region.assign_advice( @@ -272,11 +256,11 @@ impl Config { self.delta, offset, || { - let x_p = x_p.ok_or(Error::SynthesisError)?; - let x_q = x_q.ok_or(Error::SynthesisError)?; + let x_p = x_p.ok_or(Error::Synthesis)?; + let x_q = x_q.ok_or(Error::Synthesis)?; if x_q == x_p { - delta.ok_or(Error::SynthesisError) + delta.ok_or(Error::Synthesis) } else { Ok(pallas::Base::zero()) } @@ -313,7 +297,7 @@ impl Config { || "λ", self.lambda, offset, - || lambda.ok_or(Error::SynthesisError), + || lambda.ok_or(Error::Synthesis), )?; // Calculate (x_r, y_r) @@ -349,7 +333,7 @@ impl Config { || "x_r", self.x_qr, offset + 1, - || x_r.ok_or(Error::SynthesisError), + || x_r.ok_or(Error::Synthesis), )?; // Assign y_r @@ -358,7 +342,7 @@ impl Config { || "y_r", self.y_qr, offset + 1, - || y_r.ok_or(Error::SynthesisError), + || y_r.ok_or(Error::Synthesis), )?; let result = EccPoint { diff --git a/src/circuit/gadget/ecc/chip/add_incomplete.rs b/src/circuit/gadget/ecc/chip/add_incomplete.rs index 55495e1e..a5da1875 100644 --- a/src/circuit/gadget/ecc/chip/add_incomplete.rs +++ b/src/circuit/gadget/ecc/chip/add_incomplete.rs @@ -89,7 +89,7 @@ impl Config { // x_p = x_q || (x_p == x_q) { - Err(Error::SynthesisError) + Err(Error::Synthesis) } else { Ok(()) } @@ -123,7 +123,7 @@ impl Config { || "x_r", self.x_qr, offset + 1, - || x_r.ok_or(Error::SynthesisError), + || x_r.ok_or(Error::Synthesis), )?; let y_r = r.1; @@ -131,7 +131,7 @@ impl Config { || "y_r", self.y_qr, offset + 1, - || y_r.ok_or(Error::SynthesisError), + || y_r.ok_or(Error::Synthesis), )?; let result = NonIdentityEccPoint { diff --git a/src/circuit/gadget/ecc/chip/mul.rs b/src/circuit/gadget/ecc/chip/mul.rs index e3db3bde..d9814c93 100644 --- a/src/circuit/gadget/ecc/chip/mul.rs +++ b/src/circuit/gadget/ecc/chip/mul.rs @@ -305,7 +305,7 @@ impl Config { || "z_0", self.complete_config.z_complete, offset + 1, - || z_0_val.ok_or(Error::SynthesisError), + || z_0_val.ok_or(Error::Synthesis), )?; Z(CellValue::new(z_0_cell, z_0_val)) @@ -352,14 +352,14 @@ impl Config { || "x", self.add_config.x_p, offset, - || x.ok_or(Error::SynthesisError), + || x.ok_or(Error::Synthesis), )?; let y_cell = region.assign_advice( || "y", self.add_config.y_p, offset, - || y.ok_or(Error::SynthesisError), + || y.ok_or(Error::Synthesis), )?; let p = EccPoint { diff --git a/src/circuit/gadget/ecc/chip/mul/complete.rs b/src/circuit/gadget/ecc/chip/mul/complete.rs index 030f6f95..955dc179 100644 --- a/src/circuit/gadget/ecc/chip/mul/complete.rs +++ b/src/circuit/gadget/ecc/chip/mul/complete.rs @@ -143,7 +143,7 @@ impl Config { || "z", self.z_complete, row + offset + 2, - || z_val.ok_or(Error::SynthesisError), + || z_val.ok_or(Error::Synthesis), )?; Z(CellValue::new(z_cell, z_val)) }; @@ -169,7 +169,7 @@ impl Config { || "y_p", self.add_config.y_p, row + offset, - || y_p.ok_or(Error::SynthesisError), + || y_p.ok_or(Error::Synthesis), )?; CellValue::::new(y_p_cell, y_p) }; diff --git a/src/circuit/gadget/ecc/chip/mul/incomplete.rs b/src/circuit/gadget/ecc/chip/mul/incomplete.rs index b6f7d2be..55a68efe 100644 --- a/src/circuit/gadget/ecc/chip/mul/incomplete.rs +++ b/src/circuit/gadget/ecc/chip/mul/incomplete.rs @@ -229,7 +229,7 @@ impl Config { // x_p = x_a || (x_p == x_a) { - return Err(Error::SynthesisError); + return Err(Error::Synthesis); } } @@ -276,7 +276,7 @@ impl Config { || "z", self.z, row + offset, - || z_val.ok_or(Error::SynthesisError), + || z_val.ok_or(Error::Synthesis), )?; z = CellValue::new(z_cell, z_val); zs.push(Z(z)); @@ -286,13 +286,13 @@ impl Config { || "x_p", self.x_p, row + offset, - || x_p.ok_or(Error::SynthesisError), + || x_p.ok_or(Error::Synthesis), )?; region.assign_advice( || "y_p", self.y_p, row + offset, - || y_p.ok_or(Error::SynthesisError), + || y_p.ok_or(Error::Synthesis), )?; // If the bit is set, use `y`; if the bit is not set, use `-y` @@ -310,7 +310,7 @@ impl Config { || "lambda1", self.lambda1, row + offset, - || lambda1.ok_or(Error::SynthesisError), + || lambda1.ok_or(Error::Synthesis), )?; // x_R = λ1^2 - x_A - x_P @@ -332,7 +332,7 @@ impl Config { || "lambda2", self.lambda2, row + offset, - || lambda2.ok_or(Error::SynthesisError), + || lambda2.ok_or(Error::Synthesis), )?; // Compute and assign `x_a` for the next row @@ -350,7 +350,7 @@ impl Config { || "x_a", self.x_a, row + offset + 1, - || x_a_val.ok_or(Error::SynthesisError), + || x_a_val.ok_or(Error::Synthesis), )?; x_a = CellValue::new(x_a_cell, x_a_val); } @@ -361,7 +361,7 @@ impl Config { || "y_a", self.lambda1, offset + self.num_bits, - || y_a.ok_or(Error::SynthesisError), + || y_a.ok_or(Error::Synthesis), )?; CellValue::new(cell, y_a) }; diff --git a/src/circuit/gadget/ecc/chip/mul/overflow.rs b/src/circuit/gadget/ecc/chip/mul/overflow.rs index 109616b8..1a2acf3e 100644 --- a/src/circuit/gadget/ecc/chip/mul/overflow.rs +++ b/src/circuit/gadget/ecc/chip/mul/overflow.rs @@ -115,7 +115,7 @@ impl Config { || "s = alpha + k_254 â‹… 2^130", self.advices[0], 0, - || s_val.ok_or(Error::SynthesisError), + || s_val.ok_or(Error::Synthesis), )?; Ok(CellValue::new(s_cell, s_val)) }, @@ -160,7 +160,7 @@ impl Config { || "η = inv0(z_130)", self.advices[0], offset + 2, - || eta.ok_or(Error::SynthesisError), + || eta.ok_or(Error::Synthesis), )?; } diff --git a/src/circuit/gadget/ecc/chip/mul_fixed.rs b/src/circuit/gadget/ecc/chip/mul_fixed.rs index 2f470111..87c2e376 100644 --- a/src/circuit/gadget/ecc/chip/mul_fixed.rs +++ b/src/circuit/gadget/ecc/chip/mul_fixed.rs @@ -339,7 +339,7 @@ impl Config { || format!("mul_b_x, window {}", w), self.x_p, offset + w, - || x.ok_or(Error::SynthesisError), + || x.ok_or(Error::Synthesis), )?; let x = CellValue::new(x_cell, x); @@ -352,7 +352,7 @@ impl Config { || format!("mul_b_y, window {}", w), self.y_p, offset + w, - || y.ok_or(Error::SynthesisError), + || y.ok_or(Error::Synthesis), )?; let y = CellValue::new(y_cell, y); @@ -361,12 +361,7 @@ impl Config { // Assign u = (y_p + z_w).sqrt() let u_val = k_usize.map(|k| base_u[w].0[k]); - region.assign_advice( - || "u", - self.u, - offset + w, - || u_val.ok_or(Error::SynthesisError), - )?; + region.assign_advice(|| "u", self.u, offset + w, || u_val.ok_or(Error::Synthesis))?; Ok(mul_b) } @@ -431,7 +426,7 @@ impl Config { || "u", self.u, offset + NUM_WINDOWS - 1, - || u_val.ok_or(Error::SynthesisError), + || u_val.ok_or(Error::Synthesis), )?; } @@ -462,7 +457,7 @@ impl Config { || format!("mul_b_x, window {}", NUM_WINDOWS - 1), self.x_p, offset + NUM_WINDOWS - 1, - || x.ok_or(Error::SynthesisError), + || x.ok_or(Error::Synthesis), )?; let x = CellValue::new(x_cell, x); @@ -476,7 +471,7 @@ impl Config { || format!("mul_b_y, window {}", NUM_WINDOWS - 1), self.y_p, offset + NUM_WINDOWS - 1, - || y.ok_or(Error::SynthesisError), + || y.ok_or(Error::Synthesis), )?; let y = CellValue::new(y_cell, y); diff --git a/src/circuit/gadget/ecc/chip/mul_fixed/base_field_elem.rs b/src/circuit/gadget/ecc/chip/mul_fixed/base_field_elem.rs index ff05a331..4b24d00c 100644 --- a/src/circuit/gadget/ecc/chip/mul_fixed/base_field_elem.rs +++ b/src/circuit/gadget/ecc/chip/mul_fixed/base_field_elem.rs @@ -325,7 +325,7 @@ impl Config { || "α_1 = α[252..=253]", self.canon_advices[1], offset, - || alpha_1.ok_or(Error::SynthesisError), + || alpha_1.ok_or(Error::Synthesis), )?; // Witness the MSB α_2 = α[254] @@ -334,7 +334,7 @@ impl Config { || "α_2 = α[254]", self.canon_advices[2], offset, - || alpha_2.ok_or(Error::SynthesisError), + || alpha_2.ok_or(Error::Synthesis), )?; } diff --git a/src/circuit/gadget/ecc/chip/mul_fixed/full_width.rs b/src/circuit/gadget/ecc/chip/mul_fixed/full_width.rs index 7212a049..c4877089 100644 --- a/src/circuit/gadget/ecc/chip/mul_fixed/full_width.rs +++ b/src/circuit/gadget/ecc/chip/mul_fixed/full_width.rs @@ -103,7 +103,7 @@ impl Config { || format!("k[{:?}]", offset + idx), self.super_config.window, offset + idx, - || window.ok_or(Error::SynthesisError), + || window.ok_or(Error::Synthesis), )?; windows.push(CellValue::new(window_cell, window)); } diff --git a/src/circuit/gadget/ecc/chip/mul_fixed/short.rs b/src/circuit/gadget/ecc/chip/mul_fixed/short.rs index ac22756b..31a468e7 100644 --- a/src/circuit/gadget/ecc/chip/mul_fixed/short.rs +++ b/src/circuit/gadget/ecc/chip/mul_fixed/short.rs @@ -176,7 +176,7 @@ impl Config { || "y_var", self.super_config.y_p, offset, - || y_val.ok_or(Error::SynthesisError), + || y_val.ok_or(Error::Synthesis), )?; Ok(EccPoint { @@ -238,6 +238,7 @@ impl Config { pub mod tests { use group::Curve; use halo2::{ + arithmetic::CurveAffine, circuit::{Chip, Layouter}, plonk::{Any, Error}, }; @@ -391,6 +392,8 @@ pub mod tests { struct MyCircuit { magnitude: Option, sign: Option, + // For test checking + magnitude_error: Option, } impl UtilitiesInstructions for MyCircuit { @@ -463,6 +466,25 @@ pub mod tests { } } + // Copied from halo2::dev::util + fn format_value(v: pallas::Base) -> String { + use ff::Field; + if v.is_zero_vartime() { + "0".into() + } else if v == pallas::Base::one() { + "1".into() + } else if v == -pallas::Base::one() { + "-1".into() + } else { + // Format value as hex. + let s = format!("{:?}", v); + // Remove leading zeroes. + let s = s.strip_prefix("0x").unwrap(); + let s = s.trim_start_matches('0'); + format!("0x{}", s) + } + } + // Magnitude larger than 64 bits should fail { let circuits = [ @@ -470,31 +492,41 @@ pub mod tests { MyCircuit { magnitude: Some(pallas::Base::from_u128(1 << 64)), sign: Some(pallas::Base::one()), + magnitude_error: Some(pallas::Base::from(1 << 1)), }, // -2^64 MyCircuit { magnitude: Some(pallas::Base::from_u128(1 << 64)), sign: Some(-pallas::Base::one()), + magnitude_error: Some(pallas::Base::from(1 << 1)), }, // 2^66 MyCircuit { magnitude: Some(pallas::Base::from_u128(1 << 66)), sign: Some(pallas::Base::one()), + magnitude_error: Some(pallas::Base::from(1 << 3)), }, // -2^66 MyCircuit { magnitude: Some(pallas::Base::from_u128(1 << 66)), sign: Some(-pallas::Base::one()), + magnitude_error: Some(pallas::Base::from(1 << 3)), }, // 2^254 MyCircuit { magnitude: Some(pallas::Base::from_u128(1 << 127).square()), sign: Some(pallas::Base::one()), + magnitude_error: Some( + pallas::Base::from_u128(1 << 95).square() * pallas::Base::from(2), + ), }, // -2^254 MyCircuit { magnitude: Some(pallas::Base::from_u128(1 << 127).square()), sign: Some(-pallas::Base::one()), + magnitude_error: Some( + pallas::Base::from_u128(1 << 95).square() * pallas::Base::from(2), + ), }, ]; @@ -510,7 +542,11 @@ pub mod tests { "last_window_check" ) .into(), - row: 26 + row: 26, + cell_values: vec![( + ((Any::Advice, 5).into(), 0).into(), + format_value(circuit.magnitude_error.unwrap()), + )], }, VerifyFailure::Permutation { column: (Any::Fixed, 9).into(), @@ -527,9 +563,19 @@ pub mod tests { // Sign that is not +/- 1 should fail { + let magnitude_u64 = rand::random::(); let circuit = MyCircuit { - magnitude: Some(pallas::Base::from_u64(rand::random::())), + magnitude: Some(pallas::Base::from_u64(magnitude_u64)), sign: Some(pallas::Base::zero()), + magnitude_error: None, + }; + + let negation_check_y = { + *(ValueCommitV::get().generator * pallas::Scalar::from(magnitude_u64)) + .to_affine() + .coordinates() + .unwrap() + .y() }; let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); @@ -539,7 +585,8 @@ pub mod tests { VerifyFailure::ConstraintNotSatisfied { constraint: ((17, "Short fixed-base mul gate").into(), 1, "sign_check") .into(), - row: 26 + row: 26, + cell_values: vec![(((Any::Advice, 4).into(), 0).into(), "0".to_string())], }, VerifyFailure::ConstraintNotSatisfied { constraint: ( @@ -548,7 +595,18 @@ pub mod tests { "negation_check" ) .into(), - row: 26 + row: 26, + cell_values: vec![ + ( + ((Any::Advice, 1).into(), 0).into(), + format_value(negation_check_y), + ), + ( + ((Any::Advice, 3).into(), 0).into(), + format_value(negation_check_y), + ), + (((Any::Advice, 4).into(), 0).into(), "0".to_string()), + ], } ]) ); diff --git a/src/circuit/gadget/ecc/chip/witness_point.rs b/src/circuit/gadget/ecc/chip/witness_point.rs index c0a5caef..97fd1941 100644 --- a/src/circuit/gadget/ecc/chip/witness_point.rs +++ b/src/circuit/gadget/ecc/chip/witness_point.rs @@ -73,21 +73,13 @@ impl Config { ) -> Result<(CellValue, CellValue), Error> { // Assign `x` value let x_val = value.map(|value| value.0); - let x_var = region.assign_advice( - || "x", - self.x, - offset, - || x_val.ok_or(Error::SynthesisError), - )?; + let x_var = + region.assign_advice(|| "x", self.x, offset, || x_val.ok_or(Error::Synthesis))?; // Assign `y` value let y_val = value.map(|value| value.1); - let y_var = region.assign_advice( - || "y", - self.y, - offset, - || y_val.ok_or(Error::SynthesisError), - )?; + let y_var = + region.assign_advice(|| "y", self.y, offset, || y_val.ok_or(Error::Synthesis))?; Ok(( CellValue::::new(x_var, x_val), @@ -132,7 +124,7 @@ impl Config { if let Some(value) = value { // Return an error if the point is the identity. if value == pallas::Affine::identity() { - return Err(Error::SynthesisError); + return Err(Error::Synthesis); } }; diff --git a/src/circuit/gadget/poseidon/pow5.rs b/src/circuit/gadget/poseidon/pow5.rs index e6395f80..d84fb392 100644 --- a/src/circuit/gadget/poseidon/pow5.rs +++ b/src/circuit/gadget/poseidon/pow5.rs @@ -328,7 +328,7 @@ impl, const WIDTH: usize, const RATE: usize || format!("load state_{}", i), config.state[i], 0, - || value.ok_or(Error::SynthesisError), + || value.ok_or(Error::Synthesis), )?; region.constrain_equal(initial_state[i].var, var)?; Ok(StateWord { var, value }) @@ -358,7 +358,7 @@ impl, const WIDTH: usize, const RATE: usize || format!("load input_{}", i), config.state[i], 1, - || value.ok_or(Error::SynthesisError), + || value.ok_or(Error::Synthesis), )?; region.constrain_equal(constraint_var, var)?; @@ -381,7 +381,7 @@ impl, const WIDTH: usize, const RATE: usize || format!("load output_{}", i), config.state[i], 2, - || value.ok_or(Error::SynthesisError), + || value.ok_or(Error::Synthesis), )?; Ok(StateWord { var, value }) }; @@ -481,7 +481,7 @@ impl Pow5State { || format!("round_{} partial_sbox", round), config.partial_sbox, offset, - || r.as_ref().map(|r| r[0]).ok_or(Error::SynthesisError), + || r.as_ref().map(|r| r[0]).ok_or(Error::Synthesis), )?; let p_mid: Option> = m @@ -543,7 +543,7 @@ impl Pow5State { || format!("load state_{}", i), config.state[i], 0, - || value.ok_or(Error::SynthesisError), + || value.ok_or(Error::Synthesis), )?; region.constrain_equal(initial_state[i].var, var)?; Ok(StateWord { var, value }) @@ -586,7 +586,7 @@ impl Pow5State { || format!("round_{} state_{}", next_round, i), config.state[i], offset + 1, - || value.ok_or(Error::SynthesisError), + || value.ok_or(Error::Synthesis), )?; Ok(StateWord { var, value }) }; @@ -660,13 +660,13 @@ mod tests { let initial_state = layouter.assign_region( || "prepare initial state", |mut region| { - let mut state_word = |i: usize| { + let mut state_word = |i: usize| -> Result<_, Error> { let value = Some(Fp::from(i as u64)); let var = region.assign_advice( || format!("load state_{}", i), config.state[i], 0, - || value.ok_or(Error::SynthesisError), + || value.ok_or(Error::Synthesis), )?; Ok(StateWord { var, value }) }; @@ -771,13 +771,13 @@ mod tests { let message = layouter.assign_region( || "load message", |mut region| { - let mut message_word = |i: usize| { + let mut message_word = |i: usize| -> Result<_, Error> { let value = self.message.map(|message_vals| message_vals[i]); let cell = region.assign_advice( || format!("load message_{}", i), config.state[i], 0, - || value.ok_or(Error::SynthesisError), + || value.ok_or(Error::Synthesis), )?; Ok(CellValue::new(cell, value)) }; @@ -800,7 +800,7 @@ mod tests { || "load output", config.state[0], 0, - || self.output.ok_or(Error::SynthesisError), + || self.output.ok_or(Error::Synthesis), )?; region.constrain_equal(output.cell(), expected_var) }, diff --git a/src/circuit/gadget/sinsemilla/chip.rs b/src/circuit/gadget/sinsemilla/chip.rs index 8cac3fea..d9984820 100644 --- a/src/circuit/gadget/sinsemilla/chip.rs +++ b/src/circuit/gadget/sinsemilla/chip.rs @@ -268,7 +268,7 @@ impl SinsemillaInstructions { || "load private", column, 0, - || value.ok_or(Error::SynthesisError), + || value.ok_or(Error::Synthesis), )?; Ok(Var::new(cell, value)) }, @@ -80,7 +80,7 @@ where AR: Into, { let cell = region.assign_advice(annotation, column, offset, || { - copy.value.ok_or(Error::SynthesisError) + copy.value.ok_or(Error::Synthesis) })?; region.constrain_equal(cell, copy.cell)?; @@ -143,7 +143,7 @@ mod tests { use halo2::{ circuit::{Layouter, SimpleFloorPlanner}, dev::{MockProver, VerifyFailure}, - plonk::{Circuit, ConstraintSystem, Error, Selector}, + plonk::{Any, Circuit, ConstraintSystem, Error, Selector}, poly::Rotation, }; use pasta_curves::pallas; @@ -219,7 +219,8 @@ mod tests { prover.verify(), Err(vec![VerifyFailure::ConstraintNotSatisfied { constraint: ((0, "range check").into(), 0, "").into(), - row: 0 + row: 0, + cell_values: vec![(((Any::Advice, 0).into(), 0).into(), "0x8".to_string())], }]) ); } diff --git a/src/circuit/gadget/utilities/cond_swap.rs b/src/circuit/gadget/utilities/cond_swap.rs index 4d387cab..90d00138 100644 --- a/src/circuit/gadget/utilities/cond_swap.rs +++ b/src/circuit/gadget/utilities/cond_swap.rs @@ -81,7 +81,7 @@ impl CondSwapInstructions for CondSwapChip { || "witness b", config.b, 0, - || pair.1.ok_or(Error::SynthesisError), + || pair.1.ok_or(Error::Synthesis), )?; CellValue::new(cell, pair.1) }; @@ -92,7 +92,7 @@ impl CondSwapInstructions for CondSwapChip { || "swap", config.swap, 0, - || swap_val.ok_or(Error::SynthesisError), + || swap_val.ok_or(Error::Synthesis), )?; // Conditionally swap a @@ -106,7 +106,7 @@ impl CondSwapInstructions for CondSwapChip { || "a_swapped", config.a_swapped, 0, - || a_swapped.ok_or(Error::SynthesisError), + || a_swapped.ok_or(Error::Synthesis), )?; CellValue { cell: a_swapped_cell, @@ -125,7 +125,7 @@ impl CondSwapInstructions for CondSwapChip { || "b_swapped", config.b_swapped, 0, - || b_swapped.ok_or(Error::SynthesisError), + || b_swapped.ok_or(Error::Synthesis), )?; CellValue { cell: b_swapped_cell, diff --git a/src/circuit/gadget/utilities/decompose_running_sum.rs b/src/circuit/gadget/utilities/decompose_running_sum.rs index fd8c3556..c59de1c7 100644 --- a/src/circuit/gadget/utilities/decompose_running_sum.rs +++ b/src/circuit/gadget/utilities/decompose_running_sum.rs @@ -110,7 +110,7 @@ impl || "z_0 = alpha", self.z, offset, - || alpha.ok_or(Error::SynthesisError), + || alpha.ok_or(Error::Synthesis), )?; CellValue::new(cell, alpha) }; @@ -198,7 +198,7 @@ impl || format!("z_{:?}", i + 1), self.z, offset + i + 1, - || z_next_val.ok_or(Error::SynthesisError), + || z_next_val.ok_or(Error::Synthesis), )?; CellValue::new(cell, z_next_val) }; diff --git a/src/circuit/gadget/utilities/lookup_range_check.rs b/src/circuit/gadget/utilities/lookup_range_check.rs index 1b7fd682..9379b208 100644 --- a/src/circuit/gadget/utilities/lookup_range_check.rs +++ b/src/circuit/gadget/utilities/lookup_range_check.rs @@ -173,7 +173,7 @@ impl LookupRangeCheckConfig || "Witness element", self.running_sum, 0, - || value.ok_or(Error::SynthesisError), + || value.ok_or(Error::Synthesis), )?; CellValue::new(cell, value) }; @@ -251,7 +251,7 @@ impl LookupRangeCheckConfig || format!("z_{:?}", idx + 1), self.running_sum, idx + 1, - || z_val.ok_or(Error::SynthesisError), + || z_val.ok_or(Error::Synthesis), )?; CellValue::new(z_cell, z_val) @@ -311,7 +311,7 @@ impl LookupRangeCheckConfig || "Witness element", self.running_sum, 0, - || element.ok_or(Error::SynthesisError), + || element.ok_or(Error::Synthesis), )?; CellValue::new(cell, element) }; @@ -351,7 +351,7 @@ impl LookupRangeCheckConfig || format!("element * 2^({}-{})", K, num_bits), self.running_sum, 1, - || shifted.ok_or(Error::SynthesisError), + || shifted.ok_or(Error::Synthesis), )?; // Assign 2^{-num_bits} from a fixed column. From 36f1d1870584d30f0b708ebbfd61f8fba732fd1f Mon Sep 17 00:00:00 2001 From: therealyingtong Date: Fri, 19 Nov 2021 12:50:53 -0500 Subject: [PATCH 07/59] gadget::utilities: Use N - x in range_check. --- src/circuit/gadget/utilities.rs | 2 +- src/circuit_description | 338 ++++++++++++++++---------------- 2 files changed, 170 insertions(+), 170 deletions(-) diff --git a/src/circuit/gadget/utilities.rs b/src/circuit/gadget/utilities.rs index 79fc4c48..dc1bc06c 100644 --- a/src/circuit/gadget/utilities.rs +++ b/src/circuit/gadget/utilities.rs @@ -131,7 +131,7 @@ pub fn bitrange_subset(field_elem: F, bitrange: Ra /// i.e. 0 ≤ word < range. pub fn range_check(word: Expression, range: usize) -> Expression { (1..range).fold(word.clone(), |acc, i| { - acc * (word.clone() - Expression::Constant(F::from_u64(i as u64))) + acc * (Expression::Constant(F::from_u64(i as u64)) - word.clone()) }) } diff --git a/src/circuit_description b/src/circuit_description index 552652ad..edb41126 100644 --- a/src/circuit_description +++ b/src/circuit_description @@ -977,6 +977,39 @@ PinnedVerificationKey { ), ), Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 12, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( Sum( Advice { query_index: 4, @@ -998,14 +1031,14 @@ PinnedVerificationKey { ), ), ), - Negated( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - ), ), ), - Sum( + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( Sum( Advice { query_index: 4, @@ -1027,14 +1060,14 @@ PinnedVerificationKey { ), ), ), - Negated( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - ), ), ), - Sum( + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( Sum( Advice { query_index: 4, @@ -1056,14 +1089,14 @@ PinnedVerificationKey { ), ), ), - Negated( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, - ), - ), ), ), - Sum( + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( Sum( Advice { query_index: 4, @@ -1085,14 +1118,14 @@ PinnedVerificationKey { ), ), ), - Negated( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, - ), - ), ), ), - Sum( + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( Sum( Advice { query_index: 4, @@ -1114,14 +1147,14 @@ PinnedVerificationKey { ), ), ), - Negated( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, - ), - ), ), ), - Sum( + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( Sum( Advice { query_index: 4, @@ -1143,39 +1176,6 @@ PinnedVerificationKey { ), ), ), - Negated( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, - ), - ), - ), - ), - Sum( - Sum( - Advice { - query_index: 4, - column_index: 4, - rotation: Rotation( - 0, - ), - }, - Negated( - Scaled( - Advice { - query_index: 12, - column_index: 4, - rotation: Rotation( - 1, - ), - }, - 0x0000000000000000000000000000000000000000000000000000000000000008, - ), - ), - ), - Negated( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, - ), ), ), ), @@ -9534,6 +9534,25 @@ PinnedVerificationKey { ), }, Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( Advice { query_index: 4, column_index: 4, @@ -9541,14 +9560,14 @@ PinnedVerificationKey { 0, ), }, - Negated( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - ), ), ), - Sum( + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( Advice { query_index: 4, column_index: 4, @@ -9556,14 +9575,14 @@ PinnedVerificationKey { 0, ), }, - Negated( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - ), ), ), - Sum( + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( Advice { query_index: 4, column_index: 4, @@ -9571,14 +9590,14 @@ PinnedVerificationKey { 0, ), }, - Negated( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, - ), - ), ), ), - Sum( + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( Advice { query_index: 4, column_index: 4, @@ -9586,14 +9605,14 @@ PinnedVerificationKey { 0, ), }, - Negated( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, - ), - ), ), ), - Sum( + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( Advice { query_index: 4, column_index: 4, @@ -9601,14 +9620,14 @@ PinnedVerificationKey { 0, ), }, - Negated( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, - ), - ), ), ), - Sum( + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( Advice { query_index: 4, column_index: 4, @@ -9616,25 +9635,6 @@ PinnedVerificationKey { 0, ), }, - Negated( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, - ), - ), - ), - ), - Sum( - Advice { - query_index: 4, - column_index: 4, - rotation: Rotation( - 0, - ), - }, - Negated( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, - ), ), ), ), @@ -10289,30 +10289,30 @@ PinnedVerificationKey { ), ), Sum( - Sum( - Advice { - query_index: 19, - column_index: 8, - rotation: Rotation( - 1, - ), - }, - Negated( - Scaled( - Advice { - query_index: 18, - column_index: 7, - rotation: Rotation( - 1, - ), - }, - 0x0000000000000000000000000000000000000000000000000000000000000008, - ), - ), + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + Sum( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), ), ), ), @@ -10459,6 +10459,25 @@ PinnedVerificationKey { ), }, Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( Advice { query_index: 7, column_index: 7, @@ -10466,14 +10485,14 @@ PinnedVerificationKey { 0, ), }, - Negated( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - ), ), ), - Sum( + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( Advice { query_index: 7, column_index: 7, @@ -10481,25 +10500,6 @@ PinnedVerificationKey { 0, ), }, - Negated( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - ), - ), - ), - Sum( - Advice { - query_index: 7, - column_index: 7, - rotation: Rotation( - 0, - ), - }, - Negated( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, - ), ), ), ), @@ -10569,17 +10569,17 @@ PinnedVerificationKey { ), }, Sum( - Advice { - query_index: 8, - column_index: 8, - rotation: Rotation( - 0, - ), - }, + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), Negated( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, ), ), ), From 4fb434f88d11220aafb74e3de400323cdfc3aa0a Mon Sep 17 00:00:00 2001 From: therealyingtong Date: Thu, 18 Nov 2021 13:28:11 -0500 Subject: [PATCH 08/59] gadget::utilities: Use range_check in bool_check. --- src/circuit/gadget/utilities.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/circuit/gadget/utilities.rs b/src/circuit/gadget/utilities.rs index dc1bc06c..c4dca83d 100644 --- a/src/circuit/gadget/utilities.rs +++ b/src/circuit/gadget/utilities.rs @@ -102,7 +102,7 @@ pub fn transpose_option_array( /// Checks that an expresssion is either 1 or 0. pub fn bool_check(value: Expression) -> Expression { - value.clone() * (Expression::Constant(F::one()) - value) + range_check(value, 2) } /// Takes a specified subsequence of the little-endian bit representation of a field element. From 303bdc3f65914a9a1d2213baa45683042e4d7905 Mon Sep 17 00:00:00 2001 From: therealyingtong Date: Thu, 18 Nov 2021 13:47:30 -0500 Subject: [PATCH 09/59] Replace local bool_check expressions with utilities::bool_check(). --- .../gadgets/ecc/fixed-base-scalar-mul.md | 3 +- .../gadgets/ecc/var-base-scalar-mul.md | 13 ++--- src/circuit/gadget/ecc/chip/mul.rs | 17 +++++-- src/circuit/gadget/ecc/chip/mul/complete.rs | 11 +++-- src/circuit/gadget/ecc/chip/mul/incomplete.rs | 3 +- .../gadget/ecc/chip/mul_fixed/short.rs | 6 ++- src/circuit/gadget/utilities/cond_swap.rs | 8 ++-- src/circuit_description | 48 +++++++++---------- 8 files changed, 62 insertions(+), 47 deletions(-) diff --git a/book/src/design/circuit/gadgets/ecc/fixed-base-scalar-mul.md b/book/src/design/circuit/gadgets/ecc/fixed-base-scalar-mul.md index c5388a39..698ce4e0 100644 --- a/book/src/design/circuit/gadgets/ecc/fixed-base-scalar-mul.md +++ b/book/src/design/circuit/gadgets/ecc/fixed-base-scalar-mul.md @@ -102,10 +102,11 @@ $$ \begin{array}{|c|l|l|} \hline \text{Degree} & \text{Constraint} & \text{Comment} \\\hline -3 & q_\text{scalar-fixed-short} \cdot \left(k_{21} \cdot (1 - k_{21})\right) = 0 & \text{The last window must be a single bit.}\\\hline +3 & q_\text{scalar-fixed-short} \cdot \BoolCheck{k_{21}} = 0 & \text{The last window must be a single bit.}\\\hline 3 & q_\text{scalar-fixed-short} \cdot \left(s^2 - 1\right) = 0 &\text{The sign must be $1$ or $-1$.}\\\hline \end{array} $$ +where $\BoolCheck{x} = x \cdot (1 - x)$. ## Load fixed base Then, we precompute multiples of the fixed base $B$ for each window. This takes the form of a window table: $M[0..W)[0..8)$ such that: diff --git a/book/src/design/circuit/gadgets/ecc/var-base-scalar-mul.md b/book/src/design/circuit/gadgets/ecc/var-base-scalar-mul.md index 9d193db1..6f912d15 100644 --- a/book/src/design/circuit/gadgets/ecc/var-base-scalar-mul.md +++ b/book/src/design/circuit/gadgets/ecc/var-base-scalar-mul.md @@ -103,7 +103,7 @@ $\begin{array}{l} \text{Initialize } A_{254} = [2] T. \\ \\ \text{for } i \text{ from } 254 \text{ down to } 4: \\ -\hspace{1.5em} (\mathbf{k}_i)(\mathbf{k}_i-1) = 0 \\ +\hspace{1.5em} \BoolCheck{\mathbf{k}_i} = 0 \\ \hspace{1.5em} \mathbf{z}_{i} = 2\mathbf{z}_{i+1} + \mathbf{k}_{i} \\ \hspace{1.5em} x_{P,i} = x_T \\ \hspace{1.5em} y_{P,i} = (2 \mathbf{k}_i - 1) \cdot y_T \hspace{2em}\text{(conditionally negate)} \\ @@ -114,7 +114,8 @@ $\begin{array}{l} \hspace{1.5em} \lambda_{2,i} \cdot (x_{A,i} - x_{A,i-1}) = y_{A,i} + y_{A,i-1}, \\ \end{array}$ -where $x_{R,i} = (\lambda_{1,i}^2 - x_{A,i} - x_T).$ After substitution of $x_{P,i}, y_{P,i}, x_{R,i}, y_{A,i}$, and $y_{A,i-1}$, this becomes: +where $x_{R,i} = (\lambda_{1,i}^2 - x_{A,i} - x_T).$ The helper $\BoolCheck{x} = x \cdot (1 - x)$. +After substitution of $x_{P,i}, y_{P,i}, x_{R,i}, y_{A,i}$, and $y_{A,i-1}$, this becomes: $\begin{array}{l} \text{Initialize } A_{254} = [2] T. \\ @@ -122,7 +123,7 @@ $\begin{array}{l} \text{for } i \text{ from } 254 \text{ down to } 4: \\ \hspace{1.5em} \text{// let } \mathbf{k}_{i} = \mathbf{z}_{i} - 2\mathbf{z}_{i+1} \\ \hspace{1.5em} \text{// let } y_{A,i} = \frac{(\lambda_{1,i} + \lambda_{2,i}) \cdot (x_{A,i} - (\lambda_{1,i}^2 - x_{A,i} - x_T))}{2} \\[2ex] -\hspace{1.5em} (\mathbf{k}_i)(\mathbf{k}_i-1) = 0 \\ +\hspace{1.5em} \BoolCheck{\mathbf{k}_i} = 0 \\ \hspace{1.5em} \lambda_{1,i} \cdot (x_{A,i} - x_T) = y_{A,i} - (2 \mathbf{k}_i - 1) \cdot y_T \\ \hspace{1.5em} \lambda_{2,i}^2 = x_{A,i-1} + \lambda_{1,i}^2 - x_T \\[1ex] \hspace{1.5em} \begin{cases} @@ -138,7 +139,7 @@ The bits $\mathbf{k}_{3 \dots 1}$ are used in three further steps, using [comple $\begin{array}{l} \text{for } i \text{ from } 3 \text{ down to } 1: \\ \hspace{1.5em} \text{// let } \mathbf{k}_{i} = \mathbf{z}_{i} - 2\mathbf{z}_{i+1} \\[0.5ex] -\hspace{1.5em} (\mathbf{k}_i)(\mathbf{k}_i-1) = 0 \\ +\hspace{1.5em} \BoolCheck{\mathbf{k}_i} = 0 \\ \hspace{1.5em} (x_{A,i-1}, y_{A,i-1}) = \left((x_{A,i}, y_{A,i}) + (x_T, y_T)\right) + (x_{A,i}, y_{A,i}) \end{array}$ @@ -202,7 +203,7 @@ $$ \text{Degree} & \text{Constraint} \\\hline 2 & q_2 \cdot \left(x_{T,cur} - x_{T,next}\right) = 0 \\\hline 2 & q_2 \cdot \left(y_{T,cur} - y_{T,next}\right) = 0 \\\hline -3 & q_2 \cdot \mathbf{k}_i \cdot (\mathbf{k}_i - 1) = 0, \text{ where } \mathbf{k}_i = \mathbf{z}_{i} - 2\mathbf{z}_{i+1} \\\hline +3 & q_2 \cdot \BoolCheck{\mathbf{k}_i} = 0, \text{ where } \mathbf{k}_i = \mathbf{z}_{i} - 2\mathbf{z}_{i+1} \\\hline 4 & q_2 \cdot \left(\lambda_{1,i} \cdot (x_{A,i} - x_{T,i}) - y_{A,i} + (2\mathbf{k}_i - 1) \cdot y_{T,i}\right) = 0 \\\hline 3 & q_2 \cdot \left(\lambda_{2,i}^2 - x_{A,i-1} - \lambda_{1,i}^2 + x_{T,i}\right) = 0 \\\hline 3 & q_2 \cdot \left(\lambda_{2,i} \cdot (x_{A,i} - x_{A,i-1}) - y_{A,i} - y_{A,i-1}\right) = 0 \\\hline @@ -222,7 +223,7 @@ $$ \begin{array}{|c|l|} \hline \text{Degree} & \text{Constraint} \\\hline -3 & q_3 \cdot \mathbf{k}_i \cdot (\mathbf{k}_i - 1) = 0, \text{ where } \mathbf{k}_i = \mathbf{z}_{i} - 2\mathbf{z}_{i+1} \\\hline +3 & q_3 \cdot \BoolCheck{\mathbf{k}_i} = 0, \text{ where } \mathbf{k}_i = \mathbf{z}_{i} - 2\mathbf{z}_{i+1} \\\hline 4 & q_3 \cdot \left(\lambda_{1,i} \cdot (x_{A,i} - x_{T,i}) - y_{A,i} + (2\mathbf{k}_i - 1) \cdot y_{T,i}\right) = 0 \\\hline 3 & q_3 \cdot \left(\lambda_{2,i}^2 - x_{A,i-1} - \lambda_{1,i}^2 + x_{T,i}\right) = 0 \\\hline 3 & q_3 \cdot \left(\lambda_{2,i} \cdot (x_{A,i} - x_{A,i-1}) - y_{A,i} - y_{A,i-1}^\text{witnessed}\right) = 0 \\\hline diff --git a/src/circuit/gadget/ecc/chip/mul.rs b/src/circuit/gadget/ecc/chip/mul.rs index d9814c93..8c00de8a 100644 --- a/src/circuit/gadget/ecc/chip/mul.rs +++ b/src/circuit/gadget/ecc/chip/mul.rs @@ -1,5 +1,8 @@ use super::{add, CellValue, EccConfig, EccPoint, NonIdentityEccPoint, Var}; -use crate::{circuit::gadget::utilities::copy, constants::T_Q}; +use crate::{ + circuit::gadget::utilities::{bool_check, copy}, + constants::T_Q, +}; use std::ops::{Deref, Range}; use bigint::U256; @@ -109,14 +112,18 @@ impl Config { // z_0 = 2 * z_1 + k_0 // => k_0 = z_0 - 2 * z_1 let lsb = z_0 - z_1 * pallas::Base::from_u64(2); - let one_minus_lsb = Expression::Constant(pallas::Base::one()) - lsb.clone(); - let bool_check = lsb.clone() * one_minus_lsb.clone(); + let bool_check = bool_check(lsb.clone()); // `lsb` = 0 => (x_p, y_p) = (x, -y) // `lsb` = 1 => (x_p, y_p) = (0,0) - let lsb_x = (lsb.clone() * x_p.clone()) + one_minus_lsb.clone() * (x_p - base_x); - let lsb_y = (lsb * y_p.clone()) + one_minus_lsb * (y_p + base_y); + let (lsb_x, lsb_y) = { + let one_minus_lsb = Expression::Constant(pallas::Base::one()) - lsb.clone(); + let lsb_x = (lsb.clone() * x_p.clone()) + one_minus_lsb.clone() * (x_p - base_x); + let lsb_y = (lsb * y_p.clone()) + one_minus_lsb * (y_p + base_y); + + (lsb_x, lsb_y) + }; std::array::IntoIter::new([ ("bool_check", bool_check), diff --git a/src/circuit/gadget/ecc/chip/mul/complete.rs b/src/circuit/gadget/ecc/chip/mul/complete.rs index 955dc179..f3c73de0 100644 --- a/src/circuit/gadget/ecc/chip/mul/complete.rs +++ b/src/circuit/gadget/ecc/chip/mul/complete.rs @@ -1,5 +1,6 @@ use super::super::{add, copy, CellValue, EccConfig, EccPoint, Var}; use super::{COMPLETE_RANGE, X, Y, Z}; +use crate::circuit::gadget::utilities::bool_check; use halo2::{ circuit::Region, @@ -58,9 +59,8 @@ impl Config { // k_{i} = z_{i} - 2â‹…z_{i+1} let k = z_next - Expression::Constant(pallas::Base::from_u64(2)) * z_prev; - let k_minus_one = k.clone() - Expression::Constant(pallas::Base::one()); - // (k_i) â‹… (k_i - 1) = 0 - let bool_check = k.clone() * k_minus_one.clone(); + // (k_i) â‹… (1 - k_i) = 0 + let bool_check = bool_check(k.clone()); // base_y let base_y = meta.query_advice(self.z_complete, Rotation::cur()); @@ -69,7 +69,10 @@ impl Config { // k_i = 0 => y_p = -base_y // k_i = 1 => y_p = base_y - let y_switch = k_minus_one * (base_y.clone() + y_p.clone()) + k * (base_y - y_p); + let y_switch = { + let k_minus_one = k.clone() - Expression::Constant(pallas::Base::one()); + k_minus_one * (base_y.clone() + y_p.clone()) + k * (base_y - y_p) + }; std::array::IntoIter::new([("bool_check", bool_check), ("y_switch", y_switch)]) .map(move |(name, poly)| (name, q_mul_decompose_var.clone() * poly)) diff --git a/src/circuit/gadget/ecc/chip/mul/incomplete.rs b/src/circuit/gadget/ecc/chip/mul/incomplete.rs index 55a68efe..4ddac353 100644 --- a/src/circuit/gadget/ecc/chip/mul/incomplete.rs +++ b/src/circuit/gadget/ecc/chip/mul/incomplete.rs @@ -2,6 +2,7 @@ use std::ops::Deref; use super::super::{copy, CellValue, EccConfig, NonIdentityEccPoint, Var}; use super::{INCOMPLETE_HI_RANGE, INCOMPLETE_LO_RANGE, X, Y, Z}; +use crate::circuit::gadget::utilities::bool_check; use ff::Field; use halo2::{ circuit::Region, @@ -133,7 +134,7 @@ impl Config { // i from n down to 0. So z_{i+1} corresponds to the `z_prev` query. let k = z_cur - z_prev * pallas::Base::from_u64(2); // Check booleanity of decomposition. - let bool_check = k.clone() * (one.clone() - k.clone()); + let bool_check = bool_check(k.clone()); // λ_{1,i}â‹…(x_{A,i} − x_{P,i}) − y_{A,i} + (2k_i - 1) y_{P,i} = 0 let gradient_1 = lambda1_cur * (x_a_cur.clone() - x_p_cur) - y_a_cur.clone() diff --git a/src/circuit/gadget/ecc/chip/mul_fixed/short.rs b/src/circuit/gadget/ecc/chip/mul_fixed/short.rs index 31a468e7..9ff8d625 100644 --- a/src/circuit/gadget/ecc/chip/mul_fixed/short.rs +++ b/src/circuit/gadget/ecc/chip/mul_fixed/short.rs @@ -2,7 +2,9 @@ use std::{array, convert::TryInto}; use super::super::{EccConfig, EccPoint, EccScalarFixedShort}; use crate::{ - circuit::gadget::utilities::{copy, decompose_running_sum::RunningSumConfig, CellValue, Var}, + circuit::gadget::utilities::{ + bool_check, copy, decompose_running_sum::RunningSumConfig, CellValue, Var, + }, constants::{ValueCommitV, FIXED_BASE_WINDOW_SIZE, L_VALUE, NUM_WINDOWS_SHORT}, }; @@ -46,7 +48,7 @@ impl Config { let one = Expression::Constant(pallas::Base::one()); // Check that last window is either 0 or 1. - let last_window_check = last_window.clone() * (one.clone() - last_window); + let last_window_check = bool_check(last_window); // Check that sign is either 1 or -1. let sign_check = sign.clone() * sign.clone() - one; diff --git a/src/circuit/gadget/utilities/cond_swap.rs b/src/circuit/gadget/utilities/cond_swap.rs index 90d00138..92b1b3f3 100644 --- a/src/circuit/gadget/utilities/cond_swap.rs +++ b/src/circuit/gadget/utilities/cond_swap.rs @@ -1,4 +1,4 @@ -use super::{copy, CellValue, UtilitiesInstructions, Var}; +use super::{bool_check, copy, CellValue, UtilitiesInstructions, Var}; use halo2::{ circuit::{Chip, Layouter}, plonk::{Advice, Column, ConstraintSystem, Error, Expression, Selector}, @@ -179,7 +179,7 @@ impl CondSwapChip { let one = Expression::Constant(F::one()); // a_swapped - b â‹… swap - a â‹… (1-swap) = 0 - // This checks that `a_swapped` is equal to `y` when `swap` is set, + // This checks that `a_swapped` is equal to `b` when `swap` is set, // but remains as `a` when `swap` is not set. let a_check = a_swapped - b.clone() * swap.clone() - a.clone() * (one.clone() - swap.clone()); @@ -187,10 +187,10 @@ impl CondSwapChip { // b_swapped - a â‹… swap - b â‹… (1-swap) = 0 // This checks that `b_swapped` is equal to `a` when `swap` is set, // but remains as `b` when `swap` is not set. - let b_check = b_swapped - a * swap.clone() - b * (one.clone() - swap.clone()); + let b_check = b_swapped - a * swap.clone() - b * (one - swap.clone()); // Check `swap` is boolean. - let bool_check = swap.clone() * (one - swap); + let bool_check = bool_check(swap); array::IntoIter::new([a_check, b_check, bool_check]) .map(move |poly| q_swap.clone() * poly) diff --git a/src/circuit_description b/src/circuit_description index edb41126..00fee0d1 100644 --- a/src/circuit_description +++ b/src/circuit_description @@ -7418,32 +7418,32 @@ PinnedVerificationKey { ), ), Sum( - Sum( - Advice { - query_index: 10, - column_index: 9, - rotation: Rotation( - 1, - ), - }, - Negated( - Product( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Advice { - query_index: 11, - column_index: 9, - rotation: Rotation( - -1, - ), - }, - ), - ), + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + Sum( + Advice { + query_index: 10, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Advice { + query_index: 11, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + ), + ), ), ), ), From 409bbf36a0a1a538883cfc7cd2cf2790b1278ed3 Mon Sep 17 00:00:00 2001 From: therealyingtong Date: Thu, 18 Nov 2021 15:03:40 -0500 Subject: [PATCH 10/59] mul::complete: Replace k_minus_one with one_minus_k. --- src/circuit/gadget/ecc/chip/mul/complete.rs | 4 +- src/circuit_description | 48 ++++++++++----------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/circuit/gadget/ecc/chip/mul/complete.rs b/src/circuit/gadget/ecc/chip/mul/complete.rs index f3c73de0..d0b71a1a 100644 --- a/src/circuit/gadget/ecc/chip/mul/complete.rs +++ b/src/circuit/gadget/ecc/chip/mul/complete.rs @@ -70,8 +70,8 @@ impl Config { // k_i = 0 => y_p = -base_y // k_i = 1 => y_p = base_y let y_switch = { - let k_minus_one = k.clone() - Expression::Constant(pallas::Base::one()); - k_minus_one * (base_y.clone() + y_p.clone()) + k * (base_y - y_p) + let one_minus_k = Expression::Constant(pallas::Base::one()) - k.clone(); + one_minus_k * (base_y.clone() + y_p.clone()) + k * (base_y - y_p) }; std::array::IntoIter::new([("bool_check", bool_check), ("y_switch", y_switch)]) diff --git a/src/circuit_description b/src/circuit_description index 00fee0d1..30ce1e99 100644 --- a/src/circuit_description +++ b/src/circuit_description @@ -7524,32 +7524,32 @@ PinnedVerificationKey { Sum( Product( Sum( - Sum( - Advice { - query_index: 10, - column_index: 9, - rotation: Rotation( - 1, - ), - }, - Negated( - Product( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Advice { - query_index: 11, - column_index: 9, - rotation: Rotation( - -1, - ), - }, - ), - ), + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + Sum( + Advice { + query_index: 10, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Advice { + query_index: 11, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + ), + ), ), ), ), From e0a0a0d509ea47ba27fb70ae2f53646d24beb2a7 Mon Sep 17 00:00:00 2001 From: therealyingtong Date: Tue, 30 Nov 2021 09:30:43 -0500 Subject: [PATCH 11/59] book: Introduce RangeCheck macro. --- book/macros.txt | 1 + book/src/design/circuit/gadgets/decomposition.md | 2 +- .../design/circuit/gadgets/ecc/fixed-base-scalar-mul.md | 8 ++++---- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/book/macros.txt b/book/macros.txt index af590a07..d6fc74f0 100644 --- a/book/macros.txt +++ b/book/macros.txt @@ -32,4 +32,5 @@ # Circuit constraint helper methods \BoolCheck:{\texttt{bool\_check}({#1})} +\RangeCheck:{\texttt{range\_check}({#1, #2})} \ShortLookupRangeCheck:{\texttt{short\_lookup\_range\_check}({#1})} diff --git a/book/src/design/circuit/gadgets/decomposition.md b/book/src/design/circuit/gadgets/decomposition.md index 5b8eddac..2a3febeb 100644 --- a/book/src/design/circuit/gadgets/decomposition.md +++ b/book/src/design/circuit/gadgets/decomposition.md @@ -73,4 +73,4 @@ $$q_\mathit{lookup} \cdot \left(q_\mathit{running} \cdot (z_i - 2^K \cdot z_{i+1 where $z_i$ and $\textsf{word}$ are the same cell (but distinguished here for clarity of usage). ## Short range decomposition -For a short range (for instance, $[0, \texttt{range})$ where $\texttt{range} \leq 8$), we can range-constrain each word using a degree-$\texttt{range}$ polynomial constraint instead of a lookup: $$\texttt{range\_check(word, range)} = \texttt{word} \cdot (1 - \texttt{word}) \cdots (\texttt{range} - 1 - \texttt{word}).$$ +For a short range (for instance, $[0, \texttt{range})$ where $\texttt{range} \leq 8$), we can range-constrain each word using a degree-$\texttt{range}$ polynomial constraint instead of a lookup: $$\RangeCheck{word}{range} = \texttt{word} \cdot (1 - \texttt{word}) \cdots (\texttt{range} - 1 - \texttt{word}).$$ diff --git a/book/src/design/circuit/gadgets/ecc/fixed-base-scalar-mul.md b/book/src/design/circuit/gadgets/ecc/fixed-base-scalar-mul.md index 698ce4e0..244a955c 100644 --- a/book/src/design/circuit/gadgets/ecc/fixed-base-scalar-mul.md +++ b/book/src/design/circuit/gadgets/ecc/fixed-base-scalar-mul.md @@ -28,10 +28,10 @@ $$ \begin{array}{|c|l|} \hline \text{Degree} & \text{Constraint} \\\hline -9 & q_\text{decompose-base-field} \cdot \texttt{range\_check}(\text{word}, 2^3) = 0 \\\hline +9 & q_\text{decompose-base-field} \cdot \RangeCheck{\text{word}}{2^3} = 0 \\\hline \end{array} $$ -where $\texttt{range\_check}(\text{word}, \texttt{range}) = \text{word} \cdot (1 - \text{word}) \cdots (\texttt{range} - 1 - \text{word}).$ +where $\RangeCheck{\text{word}}{\texttt{range}} = \text{word} \cdot (1 - \text{word}) \cdots (\texttt{range} - 1 - \text{word}).$ ### Base field element We support using a base field element as the scalar in fixed-base multiplication. This occurs, for example, in the scalar multiplication for the nullifier computation of the Action circuit $\mathsf{DeriveNullifier_{nk}} = \mathsf{Extract}_\mathbb{P}\left(\left[(\mathsf{PRF_{nk}^{nfOrchard}}(\rho) + \psi) \bmod{q_\mathbb{P}}\right]\mathcal{K}^\mathsf{Orchard} + \mathsf{cm}\right)$: here, the scalar $$\left[(\mathsf{PRF_{nk}^{nfOrchard}}(\rho) + \psi) \bmod{q_\mathbb{P}}\right]$$ is the result of a base field addition. @@ -47,8 +47,8 @@ $$ \begin{array}{|c|l|} \hline \text{Degree} & \text{Constraint} \\\hline -5 & q_\text{canon-base-field} \cdot \texttt{range\_check}(\alpha_1, 2^2) = 0 \\\hline -3 & q_\text{canon-base-field} \cdot \texttt{range\_check}(\alpha_2, 2^1) = 0 \\\hline +5 & q_\text{canon-base-field} \cdot \RangeCheck{\alpha_1}{2^2} = 0 \\\hline +3 & q_\text{canon-base-field} \cdot \RangeCheck{\alpha_2}{2^1} = 0 \\\hline 2 & q_\text{canon-base-field} \cdot \left(z_{84} - (\alpha_1 + \alpha_2 \cdot 2^2)\right) = 0 \\\hline \end{array} $$ From b63c8685914824035e0285f460d141f3d950f53c Mon Sep 17 00:00:00 2001 From: therealyingtong Date: Wed, 3 Nov 2021 14:12:24 +0100 Subject: [PATCH 12/59] poseidon: Make Spec trait methods not take (&self) parameter. --- benches/primitives.rs | 2 +- src/circuit.rs | 3 +- src/circuit/gadget/poseidon/pow5.rs | 15 +++++----- src/primitives/poseidon.rs | 21 +++++-------- src/primitives/poseidon/p128pow5t3.rs | 43 +++++++++++---------------- src/spec.rs | 3 +- 6 files changed, 38 insertions(+), 49 deletions(-) diff --git a/benches/primitives.rs b/benches/primitives.rs index df6747b5..4d141c69 100644 --- a/benches/primitives.rs +++ b/benches/primitives.rs @@ -21,7 +21,7 @@ fn bench_primitives(c: &mut Criterion) { let message = [pallas::Base::random(rng), pallas::Base::random(rng)]; group.bench_function("2-to-1", |b| { - b.iter(|| poseidon::Hash::init(P128Pow5T3, ConstantLength).hash(message)) + b.iter(|| poseidon::Hash::<_, P128Pow5T3, _, 3, 2>::init(ConstantLength).hash(message)) }); } diff --git a/src/circuit.rs b/src/circuit.rs index f1b741dd..001a6d34 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -239,9 +239,8 @@ impl plonk::Circuit for Circuit { let ecc_config = EccChip::configure(meta, advices, lagrange_coeffs, range_check.clone()); // Configuration for the Poseidon hash. - let poseidon_config = PoseidonChip::configure( + let poseidon_config = PoseidonChip::configure::( meta, - poseidon::P128Pow5T3, // We place the state columns after the partial_sbox column so that the // pad-and-add region can be layed out more efficiently. advices[6..9].try_into().unwrap(), diff --git a/src/circuit/gadget/poseidon/pow5.rs b/src/circuit/gadget/poseidon/pow5.rs index d84fb392..f9f812ce 100644 --- a/src/circuit/gadget/poseidon/pow5.rs +++ b/src/circuit/gadget/poseidon/pow5.rs @@ -52,7 +52,6 @@ impl Pow5Chip>( meta: &mut ConstraintSystem, - spec: S, state: [Column; WIDTH], partial_sbox: Column, rc_a: [Column; WIDTH], @@ -65,7 +64,7 @@ impl Pow5Chip(meta, state, partial_sbox, rc_a, rc_b) } fn synthesize( @@ -685,7 +684,7 @@ mod tests { // For the purpose of this test, compute the real final state inline. let mut expected_final_state = [Fp::zero(), Fp::one(), Fp::from_u64(2)]; - let (round_constants, mds, _) = OrchardNullifier.constants(); + let (round_constants, mds, _) = OrchardNullifier::constants(); poseidon::permute::<_, OrchardNullifier, WIDTH, RATE>( &mut expected_final_state, &mds, @@ -758,7 +757,7 @@ mod tests { meta.enable_constant(rc_b[0]); - Pow5Chip::configure(meta, OrchardNullifier, state, partial_sbox, rc_a, rc_b) + Pow5Chip::configure::(meta, state, partial_sbox, rc_a, rc_b) } fn synthesize( @@ -811,7 +810,8 @@ mod tests { #[test] fn poseidon_hash() { let message = [Fp::rand(), Fp::rand()]; - let output = poseidon::Hash::init(OrchardNullifier, ConstantLength::<2>).hash(message); + let output = + poseidon::Hash::<_, OrchardNullifier, _, 3, 2>::init(ConstantLength::<2>).hash(message); let k = 6; let circuit = HashCircuit { @@ -829,7 +829,8 @@ mod tests { pallas::Base::from_repr(tv.input[0]).unwrap(), pallas::Base::from_repr(tv.input[1]).unwrap(), ]; - let output = poseidon::Hash::init(OrchardNullifier, ConstantLength).hash(message); + let output = + poseidon::Hash::<_, OrchardNullifier, _, 3, 2>::init(ConstantLength).hash(message); let k = 6; let circuit = HashCircuit { diff --git a/src/primitives/poseidon.rs b/src/primitives/poseidon.rs index f2892d1b..281614b0 100644 --- a/src/primitives/poseidon.rs +++ b/src/primitives/poseidon.rs @@ -47,10 +47,10 @@ pub trait Spec { /// /// This is used by the default implementation of [`Spec::constants`]. If you are /// hard-coding the constants, you may leave this unimplemented. - fn secure_mds(&self) -> usize; + fn secure_mds() -> usize; /// Generates `(round_constants, mds, mds^-1)` corresponding to this specification. - fn constants(&self) -> (Vec<[F; T]>, Mds, Mds) { + fn constants() -> (Vec<[F; T]>, Mds, Mds) { let r_f = Self::full_rounds(); let r_p = Self::partial_rounds(); @@ -69,7 +69,7 @@ pub trait Spec { }) .collect(); - let (mds, mds_inv) = mds::generate_mds::(&mut grain, self.secure_mds()); + let (mds, mds_inv) = mds::generate_mds::(&mut grain, Self::secure_mds()); (round_constants, mds, mds_inv) } @@ -167,11 +167,10 @@ pub(crate) struct Duplex, const T: usize, const impl, const T: usize, const RATE: usize> Duplex { /// Constructs a new duplex sponge for the given Poseidon specification. pub(crate) fn new( - spec: S, initial_capacity_element: F, pad_and_add: Box, &SpongeState)>, ) -> Self { - let (round_constants, mds_matrix, _) = spec.constants(); + let (round_constants, mds_matrix, _) = S::constants(); let input = [None; RATE]; let mut state = [F::zero(); T]; @@ -336,13 +335,9 @@ impl< > Hash { /// Initializes a new hasher. - pub fn init(spec: S, domain: D) -> Self { + pub fn init(domain: D) -> Self { Hash { - duplex: Duplex::new( - spec, - domain.initial_capacity_element(), - domain.pad_and_add(), - ), + duplex: Duplex::new(domain.initial_capacity_element(), domain.pad_and_add()), domain, } } @@ -371,9 +366,9 @@ mod tests { fn orchard_spec_equivalence() { let message = [pallas::Base::from_u64(6), pallas::Base::from_u64(42)]; - let (round_constants, mds, _) = OrchardNullifier.constants(); + let (round_constants, mds, _) = OrchardNullifier::constants(); - let hasher = Hash::init(OrchardNullifier, ConstantLength); + let hasher = Hash::<_, OrchardNullifier, _, 3, 2>::init(ConstantLength); let result = hasher.hash(message); // The result should be equivalent to just directly applying the permutation and diff --git a/src/primitives/poseidon/p128pow5t3.rs b/src/primitives/poseidon/p128pow5t3.rs index 31c7217c..c33a9ca6 100644 --- a/src/primitives/poseidon/p128pow5t3.rs +++ b/src/primitives/poseidon/p128pow5t3.rs @@ -25,11 +25,11 @@ impl Spec for P128Pow5T3 { val.pow_vartime(&[5]) } - fn secure_mds(&self) -> usize { + fn secure_mds() -> usize { unimplemented!() } - fn constants(&self) -> (Vec<[Fp; 3]>, Mds, Mds) { + fn constants() -> (Vec<[Fp; 3]>, Mds, Mds) { ( super::fp::ROUND_CONSTANTS[..].to_vec(), super::fp::MDS, @@ -51,11 +51,11 @@ impl Spec for P128Pow5T3 { val.pow_vartime(&[5]) } - fn secure_mds(&self) -> usize { + fn secure_mds() -> usize { unimplemented!() } - fn constants(&self) -> (Vec<[Fq; 3]>, Mds, Mds) { + fn constants() -> (Vec<[Fq; 3]>, Mds, Mds) { ( super::fq::ROUND_CONSTANTS[..].to_vec(), super::fq::MDS, @@ -80,21 +80,15 @@ mod tests { /// The same Poseidon specification as poseidon::P128Pow5T3, but constructed /// such that its constants will be generated at runtime. #[derive(Debug)] - pub struct P128Pow5T3Gen { - secure_mds: usize, - _field: PhantomData, - } + pub struct P128Pow5T3Gen(PhantomData); - impl P128Pow5T3Gen { - pub fn new(secure_mds: usize) -> Self { - P128Pow5T3Gen { - secure_mds, - _field: PhantomData::default(), - } + impl P128Pow5T3Gen { + pub fn new() -> Self { + P128Pow5T3Gen(PhantomData::default()) } } - impl Spec for P128Pow5T3Gen { + impl Spec for P128Pow5T3Gen { fn full_rounds() -> usize { 8 } @@ -107,8 +101,8 @@ mod tests { val.pow_vartime(&[5]) } - fn secure_mds(&self) -> usize { - self.secure_mds + fn secure_mds() -> usize { + SECURE_MDS } } @@ -119,8 +113,7 @@ mod tests { expected_mds: [[F; 3]; 3], expected_mds_inv: [[F; 3]; 3], ) { - let poseidon = P128Pow5T3Gen::::new(0); - let (round_constants, mds, mds_inv) = poseidon.constants(); + let (round_constants, mds, mds_inv) = P128Pow5T3Gen::::constants(); for (actual, expected) in round_constants .iter() @@ -196,7 +189,7 @@ mod tests { ]), ]; - permute::, 3, 2>(&mut input, &fp::MDS, &fp::ROUND_CONSTANTS); + permute::, 3, 2>(&mut input, &fp::MDS, &fp::ROUND_CONSTANTS); assert_eq!(input, expected_output); } @@ -247,7 +240,7 @@ mod tests { ]), ]; - permute::, 3, 2>(&mut input, &fq::MDS, &fq::ROUND_CONSTANTS); + permute::, 3, 2>(&mut input, &fq::MDS, &fq::ROUND_CONSTANTS); assert_eq!(input, expected_output); } } @@ -255,7 +248,7 @@ mod tests { #[test] fn permute_test_vectors() { { - let (round_constants, mds, _) = super::P128Pow5T3.constants(); + let (round_constants, mds, _) = super::P128Pow5T3::constants(); for tv in crate::primitives::poseidon::test_vectors::fp::permute() { let mut state = [ @@ -273,7 +266,7 @@ mod tests { } { - let (round_constants, mds, _) = super::P128Pow5T3.constants(); + let (round_constants, mds, _) = super::P128Pow5T3::constants(); for tv in crate::primitives::poseidon::test_vectors::fq::permute() { let mut state = [ @@ -299,7 +292,7 @@ mod tests { Fp::from_repr(tv.input[1]).unwrap(), ]; - let result = Hash::init(super::P128Pow5T3, ConstantLength).hash(message); + let result = Hash::<_, super::P128Pow5T3, _, 3, 2>::init(ConstantLength).hash(message); assert_eq!(result.to_repr(), tv.output); } @@ -310,7 +303,7 @@ mod tests { Fq::from_repr(tv.input[1]).unwrap(), ]; - let result = Hash::init(super::P128Pow5T3, ConstantLength).hash(message); + let result = Hash::<_, super::P128Pow5T3, _, 3, 2>::init(ConstantLength).hash(message); assert_eq!(result.to_repr(), tv.output); } diff --git a/src/spec.rs b/src/spec.rs index ddd394c6..7d1cd698 100644 --- a/src/spec.rs +++ b/src/spec.rs @@ -212,7 +212,8 @@ pub(crate) fn diversify_hash(d: &[u8; 11]) -> NonIdentityPallasPoint { /// /// [concreteprfs]: https://zips.z.cash/protocol/nu5.pdf#concreteprfs pub(crate) fn prf_nf(nk: pallas::Base, rho: pallas::Base) -> pallas::Base { - poseidon::Hash::init(poseidon::P128Pow5T3, poseidon::ConstantLength).hash([nk, rho]) + poseidon::Hash::<_, poseidon::P128Pow5T3, _, 3, 2>::init(poseidon::ConstantLength) + .hash([nk, rho]) } /// Defined in [Zcash Protocol Spec § 5.4.5.5: Orchard Key Agreement][concreteorchardkeyagreement]. From 9b765565038b8661b62cb7d72d797eb1ff420121 Mon Sep 17 00:00:00 2001 From: therealyingtong Date: Wed, 3 Nov 2021 14:37:02 +0100 Subject: [PATCH 13/59] poseidon: Make gadget tests generic over WIDTH, RATE --- src/circuit/gadget/poseidon/pow5.rs | 128 +++++++++++++++------------- src/primitives/poseidon.rs | 2 +- 2 files changed, 69 insertions(+), 61 deletions(-) diff --git a/src/circuit/gadget/poseidon/pow5.rs b/src/circuit/gadget/poseidon/pow5.rs index f9f812ce..3c1525a9 100644 --- a/src/circuit/gadget/poseidon/pow5.rs +++ b/src/circuit/gadget/poseidon/pow5.rs @@ -615,40 +615,37 @@ mod tests { }, primitives::poseidon::{self, ConstantLength, P128Pow5T3 as OrchardNullifier, Spec}, }; + use std::convert::TryInto; + use std::marker::PhantomData; - const WIDTH: usize = 3; - const RATE: usize = 2; + struct PermuteCircuit, const WIDTH: usize, const RATE: usize>( + PhantomData, + ); - struct PermuteCircuit {} - - impl Circuit for PermuteCircuit { + impl, const WIDTH: usize, const RATE: usize> Circuit + for PermuteCircuit + { type Config = Pow5Config; type FloorPlanner = SimpleFloorPlanner; fn without_witnesses(&self) -> Self { - PermuteCircuit {} + PermuteCircuit::(PhantomData) } fn configure(meta: &mut ConstraintSystem) -> Pow5Config { - let state = [ - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - ]; + let state = (0..WIDTH).map(|_| meta.advice_column()).collect::>(); let partial_sbox = meta.advice_column(); - let rc_a = [ - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - ]; - let rc_b = [ - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - ]; + let rc_a = (0..WIDTH).map(|_| meta.fixed_column()).collect::>(); + let rc_b = (0..WIDTH).map(|_| meta.fixed_column()).collect::>(); - Pow5Chip::configure::(meta, state, partial_sbox, rc_a, rc_b) + Pow5Chip::configure::( + meta, + state.try_into().unwrap(), + partial_sbox, + rc_a.try_into().unwrap(), + rc_b.try_into().unwrap(), + ) } fn synthesize( @@ -659,7 +656,7 @@ mod tests { let initial_state = layouter.assign_region( || "prepare initial state", |mut region| { - let mut state_word = |i: usize| -> Result<_, Error> { + let state_word = |i: usize| { let value = Some(Fp::from(i as u64)); let var = region.assign_advice( || format!("load state_{}", i), @@ -670,22 +667,27 @@ mod tests { Ok(StateWord { var, value }) }; - Ok([state_word(0)?, state_word(1)?, state_word(2)?]) + let state: Result, Error> = (0..WIDTH).map(state_word).collect(); + Ok(state?.try_into().unwrap()) }, )?; let chip = Pow5Chip::construct(config.clone()); let final_state = as PoseidonInstructions< Fp, - OrchardNullifier, + S, WIDTH, - 2, + RATE, >>::permute(&chip, &mut layouter, &initial_state)?; // For the purpose of this test, compute the real final state inline. - let mut expected_final_state = [Fp::zero(), Fp::one(), Fp::from_u64(2)]; - let (round_constants, mds, _) = OrchardNullifier::constants(); - poseidon::permute::<_, OrchardNullifier, WIDTH, RATE>( + let mut expected_final_state = (0..WIDTH) + .map(|idx| Fp::from_u64(idx as u64)) + .collect::>() + .try_into() + .unwrap(); + let (round_constants, mds, _) = S::constants(); + poseidon::permute::<_, S, WIDTH, RATE>( &mut expected_final_state, &mds, &round_constants, @@ -704,9 +706,11 @@ mod tests { region.constrain_equal(final_state[i].var, var) }; - final_state_word(0)?; - final_state_word(1)?; - final_state_word(2) + for i in 0..(WIDTH - 1) { + final_state_word(i)?; + } + + final_state_word(WIDTH - 1) }, ) } @@ -715,49 +719,49 @@ mod tests { #[test] fn poseidon_permute() { let k = 6; - let circuit = PermuteCircuit {}; + let circuit = PermuteCircuit::(PhantomData); let prover = MockProver::run(k, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())) } - #[derive(Default)] - struct HashCircuit { + struct HashCircuit, const WIDTH: usize, const RATE: usize> { message: Option<[Fp; 2]>, // For the purpose of this test, witness the result. // TODO: Move this into an instance column. output: Option, + _spec: PhantomData, } - impl Circuit for HashCircuit { + impl, const WIDTH: usize, const RATE: usize> Circuit + for HashCircuit + { type Config = Pow5Config; type FloorPlanner = SimpleFloorPlanner; fn without_witnesses(&self) -> Self { - Self::default() + Self { + message: None, + output: None, + _spec: PhantomData, + } } fn configure(meta: &mut ConstraintSystem) -> Pow5Config { - let state = [ - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - ]; + let state = (0..WIDTH).map(|_| meta.advice_column()).collect::>(); let partial_sbox = meta.advice_column(); - let rc_a = [ - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - ]; - let rc_b = [ - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - ]; + let rc_a = (0..WIDTH).map(|_| meta.fixed_column()).collect::>(); + let rc_b = (0..WIDTH).map(|_| meta.fixed_column()).collect::>(); meta.enable_constant(rc_b[0]); - Pow5Chip::configure::(meta, state, partial_sbox, rc_a, rc_b) + Pow5Chip::configure::( + meta, + state.try_into().unwrap(), + partial_sbox, + rc_a.try_into().unwrap(), + rc_b.try_into().unwrap(), + ) } fn synthesize( @@ -770,7 +774,7 @@ mod tests { let message = layouter.assign_region( || "load message", |mut region| { - let mut message_word = |i: usize| -> Result<_, Error> { + let message_word = |i: usize| { let value = self.message.map(|message_vals| message_vals[i]); let cell = region.assign_advice( || format!("load message_{}", i), @@ -781,14 +785,15 @@ mod tests { Ok(CellValue::new(cell, value)) }; - Ok([message_word(0)?, message_word(1)?]) + let message: Result, Error> = (0..RATE).map(message_word).collect(); + Ok(message?.try_into().unwrap()) }, )?; - let hasher = Hash::<_, _, OrchardNullifier, _, WIDTH, 2>::init( + let hasher = Hash::<_, _, S, _, WIDTH, RATE>::init( chip, layouter.namespace(|| "init"), - ConstantLength::<2>, + ConstantLength::, )?; let output = hasher.hash(layouter.namespace(|| "hash"), message)?; @@ -814,9 +819,10 @@ mod tests { poseidon::Hash::<_, OrchardNullifier, _, 3, 2>::init(ConstantLength::<2>).hash(message); let k = 6; - let circuit = HashCircuit { + let circuit = HashCircuit:: { message: Some(message), output: Some(output), + _spec: PhantomData, }; let prover = MockProver::run(k, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())) @@ -833,9 +839,10 @@ mod tests { poseidon::Hash::<_, OrchardNullifier, _, 3, 2>::init(ConstantLength).hash(message); let k = 6; - let circuit = HashCircuit { + let circuit = HashCircuit:: { message: Some(message), output: Some(output), + _spec: PhantomData, }; let prover = MockProver::run(k, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())); @@ -853,9 +860,10 @@ mod tests { .titled("Poseidon Chip Layout", ("sans-serif", 60)) .unwrap(); - let circuit = HashCircuit { + let circuit = HashCircuit:: { message: None, output: None, + _spec: PhantomData, }; halo2::dev::CircuitLayout::default() .render(6, &circuit, &root) diff --git a/src/primitives/poseidon.rs b/src/primitives/poseidon.rs index 281614b0..0921fffc 100644 --- a/src/primitives/poseidon.rs +++ b/src/primitives/poseidon.rs @@ -30,7 +30,7 @@ pub(crate) type SpongeState = [Option; RATE]; pub(crate) type Mds = [[F; T]; T]; /// A specification for a Poseidon permutation. -pub trait Spec { +pub trait Spec: fmt::Debug { /// The number of full rounds for this specification. /// /// This must be an even number. From 421891f065a1d84cfa0b6e6fcd246660dc427770 Mon Sep 17 00:00:00 2001 From: therealyingtong Date: Thu, 4 Nov 2021 02:07:28 +0100 Subject: [PATCH 14/59] Benchmark proof creation and verification for RATE = 2, 8, 11. --- Cargo.toml | 4 + benches/poseidon.rs | 255 ++++++++++++++++++++++++++++ src/circuit.rs | 2 +- src/circuit/gadget.rs | 6 +- src/circuit/gadget/poseidon.rs | 8 +- src/circuit/gadget/poseidon/pow5.rs | 22 ++- src/circuit/gadget/utilities.rs | 13 +- src/primitives/poseidon.rs | 1 + 8 files changed, 299 insertions(+), 12 deletions(-) create mode 100644 benches/poseidon.rs diff --git a/Cargo.toml b/Cargo.toml index d12d0b32..2b38917e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -77,6 +77,10 @@ harness = false name = "circuit" harness = false +[[bench]] +name = "poseidon" +harness = false + [profile.release] debug = true diff --git a/benches/poseidon.rs b/benches/poseidon.rs new file mode 100644 index 00000000..3658cfc3 --- /dev/null +++ b/benches/poseidon.rs @@ -0,0 +1,255 @@ +use ff::Field; +use halo2::{ + circuit::{Layouter, SimpleFloorPlanner}, + pasta::Fp, + plonk::{ + create_proof, keygen_pk, keygen_vk, verify_proof, Advice, Circuit, Column, + ConstraintSystem, Error, + }, + poly::commitment::Params, + transcript::{Blake2bRead, Blake2bWrite, Challenge255}, +}; +use pasta_curves::{pallas, vesta}; + +use orchard::{ + circuit::gadget::{ + poseidon::{Hash, Pow5Chip, Pow5Config}, + utilities::{CellValue, Var}, + }, + primitives::poseidon::{self, ConstantLength, Spec}, +}; +use std::convert::TryInto; +use std::marker::PhantomData; + +use criterion::{criterion_group, criterion_main, Criterion}; +use rand::rngs::OsRng; + +#[derive(Clone, Copy)] +struct HashCircuit +where + S: Spec + Clone + Copy, +{ + message: Option<[Fp; RATE]>, + // For the purpose of this test, witness the result. + // TODO: Move this into an instance column. + output: Option, + _spec: PhantomData, +} + +#[derive(Debug, Clone)] +struct MyConfig { + input: [Column; RATE], + poseidon_config: Pow5Config, +} + +impl Circuit for HashCircuit +where + S: Spec + Copy + Clone, +{ + type Config = MyConfig; + type FloorPlanner = SimpleFloorPlanner; + + fn without_witnesses(&self) -> Self { + Self { + message: None, + output: None, + _spec: PhantomData, + } + } + + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + let state = (0..WIDTH).map(|_| meta.advice_column()).collect::>(); + let partial_sbox = meta.advice_column(); + + let rc_a = (0..WIDTH).map(|_| meta.fixed_column()).collect::>(); + let rc_b = (0..WIDTH).map(|_| meta.fixed_column()).collect::>(); + + meta.enable_constant(rc_b[0]); + + Self::Config { + input: state[..RATE].try_into().unwrap(), + poseidon_config: Pow5Chip::configure::( + meta, + state.try_into().unwrap(), + partial_sbox, + rc_a.try_into().unwrap(), + rc_b.try_into().unwrap(), + ), + } + } + + fn synthesize( + &self, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + let chip = Pow5Chip::construct(config.poseidon_config.clone()); + + let message = layouter.assign_region( + || "load message", + |mut region| { + let message_word = |i: usize| { + let value = self.message.map(|message_vals| message_vals[i]); + let cell = region.assign_advice( + || format!("load message_{}", i), + config.input[i], + 0, + || value.ok_or(Error::SynthesisError), + )?; + Ok(CellValue::new(cell, value)) + }; + + let message: Result, Error> = (0..RATE).map(message_word).collect(); + Ok(message?.try_into().unwrap()) + }, + )?; + + let hasher = Hash::<_, _, S, _, WIDTH, RATE>::init( + chip, + layouter.namespace(|| "init"), + ConstantLength::, + )?; + let output = hasher.hash(layouter.namespace(|| "hash"), message)?; + + layouter.assign_region( + || "constrain output", + |mut region| { + let expected_var = region.assign_advice( + || "load output", + config.input[0], + 0, + || self.output.ok_or(Error::SynthesisError), + )?; + region.constrain_equal(output.cell(), expected_var) + }, + ) + } +} + +#[derive(Debug, Clone, Copy)] +struct MySpec; + +impl Spec for MySpec<3, 2> { + fn full_rounds() -> usize { + 8 + } + + fn partial_rounds() -> usize { + 56 + } + + fn sbox(val: Fp) -> Fp { + val.pow_vartime(&[5]) + } + + fn secure_mds() -> usize { + 0 + } +} + +impl Spec for MySpec<9, 8> { + fn full_rounds() -> usize { + 8 + } + + fn partial_rounds() -> usize { + 56 + } + + fn sbox(val: Fp) -> Fp { + val.pow_vartime(&[5]) + } + + fn secure_mds() -> usize { + 0 + } +} + +impl Spec for MySpec<12, 11> { + fn full_rounds() -> usize { + 8 + } + + fn partial_rounds() -> usize { + 56 + } + + fn sbox(val: Fp) -> Fp { + val.pow_vartime(&[5]) + } + + fn secure_mds() -> usize { + 0 + } +} + +const K: u32 = 6; + +fn bench_poseidon(name: &str, c: &mut Criterion) +where + S: Spec + Copy + Clone, +{ + // Initialize the polynomial commitment parameters + let params: Params = Params::new(K); + + let empty_circuit = HashCircuit:: { + message: None, + output: None, + _spec: PhantomData, + }; + + // Initialize the proving key + let vk = keygen_vk(¶ms, &empty_circuit).expect("keygen_vk should not fail"); + let pk = keygen_pk(¶ms, vk, &empty_circuit).expect("keygen_pk should not fail"); + + let prover_name = name.to_string() + "-prover"; + let verifier_name = name.to_string() + "-verifier"; + + let rng = OsRng; + let message = (0..RATE) + .map(|_| pallas::Base::random(rng)) + .collect::>() + .try_into() + .unwrap(); + let output = poseidon::Hash::<_, S, _, WIDTH, RATE>::init(ConstantLength::).hash(message); + + let circuit = HashCircuit:: { + message: Some(message), + output: Some(output), + _spec: PhantomData, + }; + + c.bench_function(&prover_name, |b| { + b.iter(|| { + // Create a proof + let mut transcript = Blake2bWrite::<_, _, Challenge255<_>>::init(vec![]); + create_proof(¶ms, &pk, &[circuit], &[&[]], &mut transcript) + .expect("proof generation should not fail") + }) + }); + + // Create a proof + let mut transcript = Blake2bWrite::<_, _, Challenge255<_>>::init(vec![]); + create_proof(¶ms, &pk, &[circuit], &[&[]], &mut transcript) + .expect("proof generation should not fail"); + let proof = transcript.finalize(); + + c.bench_function(&verifier_name, |b| { + b.iter(|| { + let msm = params.empty_msm(); + let mut transcript = Blake2bRead::<_, _, Challenge255<_>>::init(&proof[..]); + let guard = verify_proof(¶ms, pk.get_vk(), msm, &[&[]], &mut transcript).unwrap(); + let msm = guard.clone().use_challenges(); + assert!(msm.eval()); + }); + }); +} + +fn criterion_benchmark(c: &mut Criterion) { + bench_poseidon::, 3, 2>("WIDTH = 3, RATE = 2", c); + bench_poseidon::, 9, 8>("WIDTH = 9, RATE = 8", c); + bench_poseidon::, 12, 11>("WIDTH = 12, RATE = 11", c); +} + +criterion_group!(benches, criterion_benchmark); +criterion_main!(benches); diff --git a/src/circuit.rs b/src/circuit.rs index 001a6d34..c383b7ef 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -57,7 +57,7 @@ use std::convert::TryInto; use self::gadget::utilities::lookup_range_check::LookupRangeCheckConfig; -pub(crate) mod gadget; +pub mod gadget; /// Size of the Orchard circuit. const K: u32 = 11; diff --git a/src/circuit/gadget.rs b/src/circuit/gadget.rs index b0d8b247..4bf51c93 100644 --- a/src/circuit/gadget.rs +++ b/src/circuit/gadget.rs @@ -1,3 +1,5 @@ +//! Gadgets used in the Orchard circuit. + use pasta_curves::pallas; use ecc::chip::EccChip; @@ -5,9 +7,9 @@ use poseidon::Pow5Chip as PoseidonChip; use sinsemilla::{chip::SinsemillaChip, merkle::chip::MerkleChip}; pub(crate) mod ecc; -pub(crate) mod poseidon; +pub mod poseidon; pub(crate) mod sinsemilla; -pub(crate) mod utilities; +pub mod utilities; impl super::Config { pub(super) fn ecc_chip(&self) -> EccChip { diff --git a/src/circuit/gadget/poseidon.rs b/src/circuit/gadget/poseidon.rs index 8a891ccf..96e5917d 100644 --- a/src/circuit/gadget/poseidon.rs +++ b/src/circuit/gadget/poseidon.rs @@ -80,11 +80,13 @@ impl< const RATE: usize, > Word { - pub(crate) fn inner(&self) -> PoseidonChip::Word { + /// The word contained in this gadget. + pub fn inner(&self) -> PoseidonChip::Word { self.inner } - pub(crate) fn from_inner(inner: PoseidonChip::Word) -> Self { + /// Construct a [`Word`] gadget from the inner word. + pub fn from_inner(inner: PoseidonChip::Word) -> Self { Self { inner } } } @@ -109,6 +111,7 @@ fn poseidon_duplex< } /// A Poseidon duplex sponge. +#[derive(Debug)] pub struct Duplex< F: FieldExt, PoseidonChip: PoseidonDuplexInstructions, @@ -210,6 +213,7 @@ impl< } /// A Poseidon hash function, built around a duplex sponge. +#[derive(Debug)] pub struct Hash< F: FieldExt, PoseidonChip: PoseidonDuplexInstructions, diff --git a/src/circuit/gadget/poseidon/pow5.rs b/src/circuit/gadget/poseidon/pow5.rs index 3c1525a9..93310650 100644 --- a/src/circuit/gadget/poseidon/pow5.rs +++ b/src/circuit/gadget/poseidon/pow5.rs @@ -199,6 +199,7 @@ impl Pow5Chip) -> Self { Pow5Chip { config } } @@ -401,18 +402,13 @@ impl, const WIDTH: usize, const RATE: usize } } +/// A word in the Poseidon state. #[derive(Clone, Copy, Debug)] pub struct StateWord { var: Cell, value: Option, } -impl StateWord { - pub fn new(var: Cell, value: Option) -> Self { - Self { var, value } - } -} - impl From> for CellValue { fn from(state_word: StateWord) -> CellValue { CellValue::new(state_word.var, state_word.value) @@ -425,6 +421,20 @@ impl From> for StateWord { } } +impl Var for StateWord { + fn new(var: Cell, value: Option) -> Self { + Self { var, value } + } + + fn cell(&self) -> Cell { + self.var + } + + fn value(&self) -> Option { + self.value + } +} + #[derive(Debug)] struct Pow5State([StateWord; WIDTH]); diff --git a/src/circuit/gadget/utilities.rs b/src/circuit/gadget/utilities.rs index 79fc4c48..743bd4ea 100644 --- a/src/circuit/gadget/utilities.rs +++ b/src/circuit/gadget/utilities.rs @@ -1,3 +1,5 @@ +//! Utility gadgets. + use ff::PrimeFieldBits; use halo2::{ circuit::{Cell, Layouter, Region}, @@ -17,9 +19,15 @@ pub struct CellValue { value: Option, } +/// Trait for a variable in the circuit. pub trait Var: Copy + Clone + std::fmt::Debug { + /// Construct a new variable. fn new(cell: Cell, value: Option) -> Self; + + /// The cell at which this variable was allocated. fn cell(&self) -> Cell; + + /// The value allocated to this variable. fn value(&self) -> Option; } @@ -37,9 +45,12 @@ impl Var for CellValue { } } +/// Trait for utilities used across circuits. pub trait UtilitiesInstructions { + /// Variable in the circuit. type Var: Var; + /// Load a variable. fn load_private( &self, mut layouter: impl Layouter, @@ -88,7 +99,7 @@ where Ok(CellValue::new(cell, copy.value)) } -pub fn transpose_option_array( +pub(crate) fn transpose_option_array( option_array: Option<[T; LEN]>, ) -> [Option; LEN] { let mut ret = [None; LEN]; diff --git a/src/primitives/poseidon.rs b/src/primitives/poseidon.rs index 0921fffc..8078fac2 100644 --- a/src/primitives/poseidon.rs +++ b/src/primitives/poseidon.rs @@ -141,6 +141,7 @@ fn poseidon_duplex, const T: usize, const RATE: output } +#[derive(Debug)] pub(crate) enum Sponge { Absorbing(SpongeState), Squeezing(SpongeState), From ba75da27bb2cc4439d29cf146fea7d329dbb6b6b Mon Sep 17 00:00:00 2001 From: therealyingtong Date: Tue, 30 Nov 2021 10:39:01 -0500 Subject: [PATCH 15/59] gadget::utilities: Introduce ternary expression helper. --- src/circuit/gadget/utilities.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/circuit/gadget/utilities.rs b/src/circuit/gadget/utilities.rs index c4dca83d..5badaa0d 100644 --- a/src/circuit/gadget/utilities.rs +++ b/src/circuit/gadget/utilities.rs @@ -105,6 +105,14 @@ pub fn bool_check(value: Expression) -> Expression { range_check(value, 2) } +/// If `a` then `b`, else `c`. Returns (a * b) + (1 - a) * c. +/// +/// `a` must be a boolean-constrained expression. +pub fn ternary(a: Expression, b: Expression, c: Expression) -> Expression { + let one_minus_a = Expression::Constant(F::one()) - a.clone(); + a * b + one_minus_a * c +} + /// Takes a specified subsequence of the little-endian bit representation of a field element. /// The bits are numbered from 0 for the LSB. pub fn bitrange_subset(field_elem: F, bitrange: Range) -> F { From 9513efd6f35d81b262751ce5528fe5c214dfbe8c Mon Sep 17 00:00:00 2001 From: therealyingtong Date: Tue, 30 Nov 2021 12:52:15 -0500 Subject: [PATCH 16/59] ecc::chip::mul.rs: Use ternary helper in variable-base scalar mul. --- src/circuit/gadget/ecc/chip/mul.rs | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/circuit/gadget/ecc/chip/mul.rs b/src/circuit/gadget/ecc/chip/mul.rs index 8c00de8a..d3043995 100644 --- a/src/circuit/gadget/ecc/chip/mul.rs +++ b/src/circuit/gadget/ecc/chip/mul.rs @@ -1,6 +1,6 @@ use super::{add, CellValue, EccConfig, EccPoint, NonIdentityEccPoint, Var}; use crate::{ - circuit::gadget::utilities::{bool_check, copy}, + circuit::gadget::utilities::{bool_check, copy, ternary}, constants::T_Q, }; use std::ops::{Deref, Range}; @@ -10,7 +10,7 @@ use ff::PrimeField; use halo2::{ arithmetic::FieldExt, circuit::{Layouter, Region}, - plonk::{ConstraintSystem, Error, Expression, Selector}, + plonk::{ConstraintSystem, Error, Selector}, poly::Rotation, }; @@ -117,13 +117,8 @@ impl Config { // `lsb` = 0 => (x_p, y_p) = (x, -y) // `lsb` = 1 => (x_p, y_p) = (0,0) - let (lsb_x, lsb_y) = { - let one_minus_lsb = Expression::Constant(pallas::Base::one()) - lsb.clone(); - let lsb_x = (lsb.clone() * x_p.clone()) + one_minus_lsb.clone() * (x_p - base_x); - let lsb_y = (lsb * y_p.clone()) + one_minus_lsb * (y_p + base_y); - - (lsb_x, lsb_y) - }; + let lsb_x = ternary(lsb.clone(), x_p.clone(), x_p - base_x); + let lsb_y = ternary(lsb, y_p.clone(), y_p + base_y); std::array::IntoIter::new([ ("bool_check", bool_check), From 1a7a1255c85c4669f812b4c90a3a9e11faf99c2b Mon Sep 17 00:00:00 2001 From: therealyingtong Date: Tue, 30 Nov 2021 12:55:20 -0500 Subject: [PATCH 17/59] mul::complete.rs: Use ternary helper in complete addition part of variable-base scalar mul. --- src/circuit/gadget/ecc/chip/mul/complete.rs | 7 +- src/circuit_description | 86 ++++++++++----------- 2 files changed, 45 insertions(+), 48 deletions(-) diff --git a/src/circuit/gadget/ecc/chip/mul/complete.rs b/src/circuit/gadget/ecc/chip/mul/complete.rs index d0b71a1a..4c88cef9 100644 --- a/src/circuit/gadget/ecc/chip/mul/complete.rs +++ b/src/circuit/gadget/ecc/chip/mul/complete.rs @@ -1,6 +1,6 @@ use super::super::{add, copy, CellValue, EccConfig, EccPoint, Var}; use super::{COMPLETE_RANGE, X, Y, Z}; -use crate::circuit::gadget::utilities::bool_check; +use crate::circuit::gadget::utilities::{bool_check, ternary}; use halo2::{ circuit::Region, @@ -69,10 +69,7 @@ impl Config { // k_i = 0 => y_p = -base_y // k_i = 1 => y_p = base_y - let y_switch = { - let one_minus_k = Expression::Constant(pallas::Base::one()) - k.clone(); - one_minus_k * (base_y.clone() + y_p.clone()) + k * (base_y - y_p) - }; + let y_switch = ternary(k, base_y.clone() - y_p.clone(), base_y + y_p); std::array::IntoIter::new([("bool_check", bool_check), ("y_switch", y_switch)]) .map(move |(name, poly)| (name, q_mul_decompose_var.clone() * poly)) diff --git a/src/circuit_description b/src/circuit_description index 30ce1e99..ae90619e 100644 --- a/src/circuit_description +++ b/src/circuit_description @@ -7522,6 +7522,49 @@ PinnedVerificationKey { ), ), Sum( + Product( + Sum( + Advice { + query_index: 10, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Advice { + query_index: 11, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 21, + column_index: 1, + rotation: Rotation( + -1, + ), + }, + ), + ), + ), Product( Sum( Constant( @@ -7570,49 +7613,6 @@ PinnedVerificationKey { }, ), ), - Product( - Sum( - Advice { - query_index: 10, - column_index: 9, - rotation: Rotation( - 1, - ), - }, - Negated( - Product( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Advice { - query_index: 11, - column_index: 9, - rotation: Rotation( - -1, - ), - }, - ), - ), - ), - Sum( - Advice { - query_index: 9, - column_index: 9, - rotation: Rotation( - 0, - ), - }, - Negated( - Advice { - query_index: 21, - column_index: 1, - rotation: Rotation( - -1, - ), - }, - ), - ), - ), ), ), Product( From 76c8bb9711bb4a4a8b9a4a21dd6f50a40c58ae3c Mon Sep 17 00:00:00 2001 From: therealyingtong Date: Tue, 30 Nov 2021 13:06:09 -0500 Subject: [PATCH 18/59] utilities::cond_swap: Use ternary helper in cond_swap. Co-authored-by: Jack Grigg --- src/circuit/gadget/utilities/cond_swap.rs | 13 +- src/circuit_description | 304 +++++++++++----------- 2 files changed, 152 insertions(+), 165 deletions(-) diff --git a/src/circuit/gadget/utilities/cond_swap.rs b/src/circuit/gadget/utilities/cond_swap.rs index 92b1b3f3..6eb0a33e 100644 --- a/src/circuit/gadget/utilities/cond_swap.rs +++ b/src/circuit/gadget/utilities/cond_swap.rs @@ -1,7 +1,7 @@ -use super::{bool_check, copy, CellValue, UtilitiesInstructions, Var}; +use super::{bool_check, copy, ternary, CellValue, UtilitiesInstructions, Var}; use halo2::{ circuit::{Chip, Layouter}, - plonk::{Advice, Column, ConstraintSystem, Error, Expression, Selector}, + plonk::{Advice, Column, ConstraintSystem, Error, Selector}, poly::Rotation, }; use pasta_curves::arithmetic::FieldExt; @@ -176,18 +176,13 @@ impl CondSwapChip { let b_swapped = meta.query_advice(config.b_swapped, Rotation::cur()); let swap = meta.query_advice(config.swap, Rotation::cur()); - let one = Expression::Constant(F::one()); - - // a_swapped - b â‹… swap - a â‹… (1-swap) = 0 // This checks that `a_swapped` is equal to `b` when `swap` is set, // but remains as `a` when `swap` is not set. - let a_check = - a_swapped - b.clone() * swap.clone() - a.clone() * (one.clone() - swap.clone()); + let a_check = a_swapped - ternary(swap.clone(), b.clone(), a.clone()); - // b_swapped - a â‹… swap - b â‹… (1-swap) = 0 // This checks that `b_swapped` is equal to `a` when `swap` is set, // but remains as `b` when `swap` is not set. - let b_check = b_swapped - a * swap.clone() - b * (one - swap.clone()); + let b_check = b_swapped - ternary(swap.clone(), a, b); // Check `swap` is boolean. let bool_check = bool_check(swap); diff --git a/src/circuit_description b/src/circuit_description index ae90619e..c09e858e 100644 --- a/src/circuit_description +++ b/src/circuit_description @@ -13457,23 +13457,16 @@ PinnedVerificationKey { ), ), Sum( - Sum( - Advice { - query_index: 2, - column_index: 2, - rotation: Rotation( - 0, - ), - }, - Negated( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( Product( - Advice { - query_index: 1, - column_index: 1, - rotation: Rotation( - 0, - ), - }, Advice { query_index: 4, column_index: 4, @@ -13481,31 +13474,36 @@ PinnedVerificationKey { 0, ), }, + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, ), - ), - ), - Negated( - Product( - Advice { - query_index: 0, - column_index: 0, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Advice { - query_index: 4, - column_index: 4, - rotation: Rotation( - 0, - ), - }, + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), ), + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, ), ), ), @@ -13568,23 +13566,16 @@ PinnedVerificationKey { ), ), Sum( - Sum( - Advice { - query_index: 3, - column_index: 3, - rotation: Rotation( - 0, - ), - }, - Negated( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( Product( - Advice { - query_index: 0, - column_index: 0, - rotation: Rotation( - 0, - ), - }, Advice { query_index: 4, column_index: 4, @@ -13592,31 +13583,36 @@ PinnedVerificationKey { 0, ), }, + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, ), - ), - ), - Negated( - Product( - Advice { - query_index: 1, - column_index: 1, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Advice { - query_index: 4, - column_index: 4, - rotation: Rotation( - 0, - ), - }, + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), ), + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, ), ), ), @@ -14817,23 +14813,16 @@ PinnedVerificationKey { ), ), Sum( - Sum( - Advice { - query_index: 7, - column_index: 7, - rotation: Rotation( - 0, - ), - }, - Negated( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( Product( - Advice { - query_index: 6, - column_index: 6, - rotation: Rotation( - 0, - ), - }, Advice { query_index: 9, column_index: 9, @@ -14841,31 +14830,36 @@ PinnedVerificationKey { 0, ), }, + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, ), - ), - ), - Negated( - Product( - Advice { - query_index: 5, - column_index: 5, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Advice { - query_index: 9, - column_index: 9, - rotation: Rotation( - 0, - ), - }, + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), ), + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, ), ), ), @@ -14976,23 +14970,16 @@ PinnedVerificationKey { ), ), Sum( - Sum( - Advice { - query_index: 8, - column_index: 8, - rotation: Rotation( - 0, - ), - }, - Negated( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( Product( - Advice { - query_index: 5, - column_index: 5, - rotation: Rotation( - 0, - ), - }, Advice { query_index: 9, column_index: 9, @@ -15000,31 +14987,36 @@ PinnedVerificationKey { 0, ), }, + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, ), - ), - ), - Negated( - Product( - Advice { - query_index: 6, - column_index: 6, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Advice { - query_index: 9, - column_index: 9, - rotation: Rotation( - 0, - ), - }, + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), ), + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, ), ), ), From b02628d2632b7feed6944285333a5ccf610436b0 Mon Sep 17 00:00:00 2001 From: ying tong Date: Tue, 30 Nov 2021 20:08:56 -0500 Subject: [PATCH 19/59] Apply suggestions from code review Co-authored-by: str4d --- benches/poseidon.rs | 41 ++++++++++++++++------------- src/circuit/gadget/poseidon/pow5.rs | 27 +++++++++++-------- 2 files changed, 38 insertions(+), 30 deletions(-) diff --git a/benches/poseidon.rs b/benches/poseidon.rs index 3658cfc3..4f40d9a6 100644 --- a/benches/poseidon.rs +++ b/benches/poseidon.rs @@ -25,11 +25,11 @@ use criterion::{criterion_group, criterion_main, Criterion}; use rand::rngs::OsRng; #[derive(Clone, Copy)] -struct HashCircuit +struct HashCircuit where S: Spec + Clone + Copy, { - message: Option<[Fp; RATE]>, + message: Option<[Fp; L]>, // For the purpose of this test, witness the result. // TODO: Move this into an instance column. output: Option, @@ -37,16 +37,17 @@ where } #[derive(Debug, Clone)] -struct MyConfig { - input: [Column; RATE], +struct MyConfig { + input: [Column; L], poseidon_config: Pow5Config, } -impl Circuit for HashCircuit +impl Circuit + for HashCircuit where S: Spec + Copy + Clone, { - type Config = MyConfig; + type Config = MyConfig; type FloorPlanner = SimpleFloorPlanner; fn without_witnesses(&self) -> Self { @@ -94,12 +95,12 @@ where || format!("load message_{}", i), config.input[i], 0, - || value.ok_or(Error::SynthesisError), + || value.ok_or(Error::Synthesis), )?; Ok(CellValue::new(cell, value)) }; - let message: Result, Error> = (0..RATE).map(message_word).collect(); + let message: Result, Error> = (0..L).map(message_word).collect(); Ok(message?.try_into().unwrap()) }, )?; @@ -107,7 +108,7 @@ where let hasher = Hash::<_, _, S, _, WIDTH, RATE>::init( chip, layouter.namespace(|| "init"), - ConstantLength::, + ConstantLength::, )?; let output = hasher.hash(layouter.namespace(|| "hash"), message)?; @@ -118,7 +119,7 @@ where || "load output", config.input[0], 0, - || self.output.ok_or(Error::SynthesisError), + || self.output.ok_or(Error::Synthesis), )?; region.constrain_equal(output.cell(), expected_var) }, @@ -185,14 +186,16 @@ impl Spec for MySpec<12, 11> { const K: u32 = 6; -fn bench_poseidon(name: &str, c: &mut Criterion) -where +fn bench_poseidon( + name: &str, + c: &mut Criterion, +) where S: Spec + Copy + Clone, { // Initialize the polynomial commitment parameters let params: Params = Params::new(K); - let empty_circuit = HashCircuit:: { + let empty_circuit = HashCircuit:: { message: None, output: None, _spec: PhantomData, @@ -206,14 +209,14 @@ where let verifier_name = name.to_string() + "-verifier"; let rng = OsRng; - let message = (0..RATE) + let message = (0..L) .map(|_| pallas::Base::random(rng)) .collect::>() .try_into() .unwrap(); - let output = poseidon::Hash::<_, S, _, WIDTH, RATE>::init(ConstantLength::).hash(message); + let output = poseidon::Hash::<_, S, _, WIDTH, RATE>::init(ConstantLength::).hash(message); - let circuit = HashCircuit:: { + let circuit = HashCircuit:: { message: Some(message), output: Some(output), _spec: PhantomData, @@ -246,9 +249,9 @@ where } fn criterion_benchmark(c: &mut Criterion) { - bench_poseidon::, 3, 2>("WIDTH = 3, RATE = 2", c); - bench_poseidon::, 9, 8>("WIDTH = 9, RATE = 8", c); - bench_poseidon::, 12, 11>("WIDTH = 12, RATE = 11", c); + bench_poseidon::, 3, 2, 2>("WIDTH = 3, RATE = 2", c); + bench_poseidon::, 9, 8, 8>("WIDTH = 9, RATE = 8", c); + bench_poseidon::, 12, 11, 11>("WIDTH = 12, RATE = 11", c); } criterion_group!(benches, criterion_benchmark); diff --git a/src/circuit/gadget/poseidon/pow5.rs b/src/circuit/gadget/poseidon/pow5.rs index 93310650..f6829791 100644 --- a/src/circuit/gadget/poseidon/pow5.rs +++ b/src/circuit/gadget/poseidon/pow5.rs @@ -716,11 +716,11 @@ mod tests { region.constrain_equal(final_state[i].var, var) }; - for i in 0..(WIDTH - 1) { + for i in 0..(WIDTH) { final_state_word(i)?; } - final_state_word(WIDTH - 1) + Ok(()) }, ) } @@ -734,16 +734,21 @@ mod tests { assert_eq!(prover.verify(), Ok(())) } - struct HashCircuit, const WIDTH: usize, const RATE: usize> { - message: Option<[Fp; 2]>, + struct HashCircuit< + S: Spec, + const WIDTH: usize, + const RATE: usize, + const L: usize, + > { + message: Option<[Fp; L]>, // For the purpose of this test, witness the result. // TODO: Move this into an instance column. output: Option, _spec: PhantomData, } - impl, const WIDTH: usize, const RATE: usize> Circuit - for HashCircuit + impl, const WIDTH: usize, const RATE: usize, const L: usize> + Circuit for HashCircuit { type Config = Pow5Config; type FloorPlanner = SimpleFloorPlanner; @@ -795,7 +800,7 @@ mod tests { Ok(CellValue::new(cell, value)) }; - let message: Result, Error> = (0..RATE).map(message_word).collect(); + let message: Result, Error> = (0..L).map(message_word).collect(); Ok(message?.try_into().unwrap()) }, )?; @@ -803,7 +808,7 @@ mod tests { let hasher = Hash::<_, _, S, _, WIDTH, RATE>::init( chip, layouter.namespace(|| "init"), - ConstantLength::, + ConstantLength::, )?; let output = hasher.hash(layouter.namespace(|| "hash"), message)?; @@ -829,7 +834,7 @@ mod tests { poseidon::Hash::<_, OrchardNullifier, _, 3, 2>::init(ConstantLength::<2>).hash(message); let k = 6; - let circuit = HashCircuit:: { + let circuit = HashCircuit:: { message: Some(message), output: Some(output), _spec: PhantomData, @@ -849,7 +854,7 @@ mod tests { poseidon::Hash::<_, OrchardNullifier, _, 3, 2>::init(ConstantLength).hash(message); let k = 6; - let circuit = HashCircuit:: { + let circuit = HashCircuit:: { message: Some(message), output: Some(output), _spec: PhantomData, @@ -870,7 +875,7 @@ mod tests { .titled("Poseidon Chip Layout", ("sans-serif", 60)) .unwrap(); - let circuit = HashCircuit:: { + let circuit = HashCircuit:: { message: None, output: None, _spec: PhantomData, From 9d8fee29c79d98c49f459ff2d87ada6d7ed3bd52 Mon Sep 17 00:00:00 2001 From: therealyingtong Date: Tue, 30 Nov 2021 13:47:52 -0500 Subject: [PATCH 20/59] chip::witness_point: Refactor witness_point::Config. --- src/circuit/gadget/ecc/chip.rs | 22 +- src/circuit/gadget/ecc/chip/witness_point.rs | 34 +- src/circuit_description | 1038 +++++++++--------- 3 files changed, 547 insertions(+), 547 deletions(-) diff --git a/src/circuit/gadget/ecc/chip.rs b/src/circuit/gadget/ecc/chip.rs index f9e18265..956330b4 100644 --- a/src/circuit/gadget/ecc/chip.rs +++ b/src/circuit/gadget/ecc/chip.rs @@ -165,10 +165,8 @@ pub struct EccConfig { /// when the scalar is a signed short exponent or a base-field element. pub q_mul_fixed_running_sum: Selector, - /// Witness point (can be identity) - pub q_point: Selector, - /// Witness non-identity point - pub q_point_non_id: Selector, + /// Witness point + witness_point: witness_point::Config, /// Lookup range check using 10-bit lookup table pub lookup_config: LookupRangeCheckConfig, @@ -249,6 +247,9 @@ impl EccChip { let running_sum_config = RunningSumConfig::configure(meta, q_mul_fixed_running_sum, advices[4]); + // Create witness point gate + let witness_point = witness_point::Config::configure(meta, advices[0], advices[1]); + let config = EccConfig { advices, lagrange_coeffs, @@ -264,18 +265,11 @@ impl EccChip { q_mul_fixed_short: meta.selector(), q_mul_fixed_base_field: meta.selector(), q_mul_fixed_running_sum, - q_point: meta.selector(), - q_point_non_id: meta.selector(), + witness_point, lookup_config: range_check, running_sum_config, }; - // Create witness point gate - { - let config: witness_point::Config = (&config).into(); - config.create_gate(meta); - } - // Create incomplete point addition gate { let config: add_incomplete::Config = (&config).into(); @@ -408,7 +402,7 @@ impl EccInstructions for EccChip { layouter: &mut impl Layouter, value: Option, ) -> Result { - let config: witness_point::Config = self.config().into(); + let config = self.config().witness_point; layouter.assign_region( || "witness point", |mut region| config.point(value, 0, &mut region), @@ -420,7 +414,7 @@ impl EccInstructions for EccChip { layouter: &mut impl Layouter, value: Option, ) -> Result { - let config: witness_point::Config = self.config().into(); + let config = self.config().witness_point; layouter.assign_region( || "witness non-identity point", |mut region| config.point_non_id(value, 0, &mut region), diff --git a/src/circuit/gadget/ecc/chip/witness_point.rs b/src/circuit/gadget/ecc/chip/witness_point.rs index 97fd1941..923f64aa 100644 --- a/src/circuit/gadget/ecc/chip/witness_point.rs +++ b/src/circuit/gadget/ecc/chip/witness_point.rs @@ -1,4 +1,4 @@ -use super::{CellValue, EccConfig, EccPoint, NonIdentityEccPoint, Var}; +use super::{CellValue, EccPoint, NonIdentityEccPoint, Var}; use group::prime::PrimeCurveAffine; @@ -9,7 +9,7 @@ use halo2::{ }; use pasta_curves::{arithmetic::CurveAffine, pallas}; -#[derive(Clone, Debug)] +#[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct Config { q_point: Selector, q_point_non_id: Selector, @@ -19,19 +19,25 @@ pub struct Config { pub y: Column, } -impl From<&EccConfig> for Config { - fn from(ecc_config: &EccConfig) -> Self { - Self { - q_point: ecc_config.q_point, - q_point_non_id: ecc_config.q_point_non_id, - x: ecc_config.advices[0], - y: ecc_config.advices[1], - } - } -} - impl Config { - pub(super) fn create_gate(&self, meta: &mut ConstraintSystem) { + pub(super) fn configure( + meta: &mut ConstraintSystem, + x: Column, + y: Column, + ) -> Self { + let config = Self { + q_point: meta.selector(), + q_point_non_id: meta.selector(), + x, + y, + }; + + config.create_gate(meta); + + config + } + + fn create_gate(&self, meta: &mut ConstraintSystem) { let curve_eqn = |meta: &mut VirtualCells| { let x = meta.query_advice(self.x, Rotation::cur()); let y = meta.query_advice(self.y, Rotation::cur()); diff --git a/src/circuit_description b/src/circuit_description index c09e858e..8b6cb01d 100644 --- a/src/circuit_description +++ b/src/circuit_description @@ -44,18 +44,6 @@ PinnedVerificationKey { index: 20, column_type: Fixed, }, - Column { - index: 18, - column_type: Fixed, - }, - Column { - index: 18, - column_type: Fixed, - }, - Column { - index: 18, - column_type: Fixed, - }, Column { index: 20, column_type: Fixed, @@ -64,6 +52,22 @@ PinnedVerificationKey { index: 20, column_type: Fixed, }, + Column { + index: 18, + column_type: Fixed, + }, + Column { + index: 18, + column_type: Fixed, + }, + Column { + index: 18, + column_type: Fixed, + }, + Column { + index: 21, + column_type: Fixed, + }, Column { index: 21, column_type: Fixed, @@ -84,24 +88,20 @@ PinnedVerificationKey { index: 22, column_type: Fixed, }, - Column { - index: 21, - column_type: Fixed, - }, Column { index: 23, column_type: Fixed, }, Column { - index: 23, + index: 22, column_type: Fixed, }, Column { - index: 23, + index: 22, column_type: Fixed, }, Column { - index: 23, + index: 22, column_type: Fixed, }, Column { @@ -1186,20 +1186,20 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 23, - column_index: 23, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 23, - column_index: 23, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -1213,8 +1213,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 23, - column_index: 23, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -1228,8 +1228,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 23, - column_index: 23, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -1304,20 +1304,20 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 23, - column_index: 23, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 23, - column_index: 23, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -1331,8 +1331,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 23, - column_index: 23, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -1346,8 +1346,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 23, - column_index: 23, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -1421,8 +1421,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 23, - column_index: 23, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -1433,8 +1433,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 23, - column_index: 23, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -1444,12 +1444,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 23, - column_index: 23, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -1463,8 +1463,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 23, - column_index: 23, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -1538,7 +1538,7 @@ PinnedVerificationKey { }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -1553,7 +1553,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -1702,7 +1702,7 @@ PinnedVerificationKey { }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -1717,7 +1717,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -1852,7 +1852,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -1867,7 +1867,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -1978,7 +1978,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -1993,7 +1993,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -2117,7 +2117,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -2132,7 +2132,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -2261,7 +2261,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -2276,7 +2276,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -2405,7 +2405,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -2420,7 +2420,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -2547,7 +2547,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -2562,7 +2562,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -2689,7 +2689,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -2704,7 +2704,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -2789,7 +2789,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -2804,7 +2804,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -2889,7 +2889,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -2904,7 +2904,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -2989,7 +2989,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -3004,7 +3004,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -3089,7 +3089,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -3104,7 +3104,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -3218,7 +3218,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -3233,7 +3233,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -3323,37 +3323,21 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 21, - column_index: 21, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 21, - column_index: 21, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -3367,8 +3351,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -3378,12 +3362,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -3447,37 +3431,21 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 21, - column_index: 21, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 21, - column_index: 21, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -3491,8 +3459,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -3502,12 +3470,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -3600,37 +3568,21 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 21, - column_index: 21, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 21, - column_index: 21, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -3644,8 +3596,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -3655,12 +3607,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -5682,21 +5634,37 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 20, - column_index: 20, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -5706,12 +5674,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -5721,12 +5689,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -5820,21 +5788,37 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 20, - column_index: 20, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -5844,12 +5828,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -5859,12 +5843,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -5895,21 +5879,37 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 20, - column_index: 20, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -5919,12 +5919,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -5934,12 +5934,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -5970,21 +5970,37 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 20, - column_index: 20, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -5994,12 +6010,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -6009,12 +6025,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -6078,21 +6094,37 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 20, - column_index: 20, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -6102,12 +6134,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -6117,12 +6149,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -6278,21 +6310,37 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 20, - column_index: 20, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -6302,12 +6350,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -6317,12 +6365,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -6415,21 +6463,37 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 20, - column_index: 20, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -6439,12 +6503,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -6454,12 +6518,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -6657,7 +6721,7 @@ PinnedVerificationKey { }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -6672,7 +6736,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -6781,7 +6845,7 @@ PinnedVerificationKey { }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -6796,7 +6860,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -6997,7 +7061,7 @@ PinnedVerificationKey { }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -7012,7 +7076,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -7150,7 +7214,7 @@ PinnedVerificationKey { }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -7165,7 +7229,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -7350,7 +7414,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -7365,7 +7429,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -7478,7 +7542,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -7493,7 +7557,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -7659,7 +7723,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -7674,7 +7738,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -7769,7 +7833,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -7784,7 +7848,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -7867,7 +7931,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -7882,7 +7946,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -7963,7 +8027,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -7978,7 +8042,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -8052,7 +8116,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -8067,7 +8131,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -9018,8 +9082,8 @@ PinnedVerificationKey { ), Product( Fixed { - query_index: 22, - column_index: 22, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -9405,8 +9469,8 @@ PinnedVerificationKey { ), Product( Fixed { - query_index: 22, - column_index: 22, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -9452,8 +9516,8 @@ PinnedVerificationKey { ), Product( Fixed { - query_index: 22, - column_index: 22, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -9513,8 +9577,8 @@ PinnedVerificationKey { ), Product( Fixed { - query_index: 22, - column_index: 22, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -9643,37 +9707,21 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 21, - column_index: 21, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 21, - column_index: 21, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -9687,8 +9735,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -9702,8 +9750,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -9739,37 +9787,21 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 21, - column_index: 21, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 21, - column_index: 21, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -9783,8 +9815,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -9798,8 +9830,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -9835,37 +9867,21 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 21, - column_index: 21, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 21, - column_index: 21, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -9879,8 +9895,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -9894,8 +9910,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -9944,37 +9960,21 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 21, - column_index: 21, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 21, - column_index: 21, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -9988,8 +9988,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -10003,8 +10003,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -10045,20 +10045,20 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 23, - column_index: 23, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { - query_index: 23, - column_index: 23, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -10068,12 +10068,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 23, - column_index: 23, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -10087,8 +10087,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 23, - column_index: 23, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -10118,20 +10118,20 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 23, - column_index: 23, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { - query_index: 23, - column_index: 23, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -10141,12 +10141,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 23, - column_index: 23, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -10160,8 +10160,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 23, - column_index: 23, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -10207,20 +10207,20 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 23, - column_index: 23, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { - query_index: 23, - column_index: 23, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -10230,12 +10230,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 23, - column_index: 23, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -10249,8 +10249,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 23, - column_index: 23, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -10324,20 +10324,20 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 23, - column_index: 23, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { - query_index: 23, - column_index: 23, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -10347,12 +10347,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 23, - column_index: 23, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -10366,8 +10366,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 23, - column_index: 23, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -10397,20 +10397,20 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 23, - column_index: 23, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { - query_index: 23, - column_index: 23, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -10420,12 +10420,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 23, - column_index: 23, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -10439,8 +10439,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 23, - column_index: 23, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -10509,20 +10509,20 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 23, - column_index: 23, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { - query_index: 23, - column_index: 23, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -10532,12 +10532,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 23, - column_index: 23, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -10551,8 +10551,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 23, - column_index: 23, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -10589,20 +10589,20 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 23, - column_index: 23, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { - query_index: 23, - column_index: 23, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -10612,12 +10612,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 23, - column_index: 23, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -10631,8 +10631,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 23, - column_index: 23, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -10676,20 +10676,20 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 23, - column_index: 23, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { - query_index: 23, - column_index: 23, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -10699,12 +10699,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 23, - column_index: 23, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -10718,8 +10718,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 23, - column_index: 23, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -10777,8 +10777,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 23, - column_index: 23, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -10789,8 +10789,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 23, - column_index: 23, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -10804,8 +10804,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 23, - column_index: 23, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -10819,8 +10819,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 23, - column_index: 23, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -11122,8 +11122,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 23, - column_index: 23, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -11134,8 +11134,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 23, - column_index: 23, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -11149,8 +11149,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 23, - column_index: 23, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -11164,8 +11164,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 23, - column_index: 23, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -11467,8 +11467,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 23, - column_index: 23, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -11479,8 +11479,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 23, - column_index: 23, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -11494,8 +11494,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 23, - column_index: 23, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -11509,8 +11509,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 23, - column_index: 23, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -28334,10 +28334,10 @@ PinnedVerificationKey { (0x13d0bd76da4ace22c0e90b098d6073551322b8c734bf37eeca67fbf19687f550, 0x3d996cc9da5a31cefb453390b906eabbcc75797bc6a6b9c9e3af2fe7b6b8beed), (0x04cad7405b492a30db0a710c842cecc97d02059acf4c02aa79626dce68ac4837, 0x3d6d7b6698b258e61ebe0b25d9cbcd4a016cb0a2ae8d92752532d98cfb27720d), (0x0974ad1a3c0eb4c8d2c59cd820a82b7f28ea2f7a245008d403815131ff30879e, 0x00bb593cdf920cef4965f788d65eba3c3aa07d9718dfb62e3e385849a0d692a8), - (0x129898b6bcca9f9ff44f5dc76cb26bc229fa8b14ff47d9153680b0ba5c5efbf6, 0x1be1a12569bd9d26ac6225d404a52099198520eebec3ae1ef5de8a18d74b6116), - (0x3f30174d44efaca9cb31c8b6b6f4f4aaeedba6a974ea72f16ea9259099054bdc, 0x1f0de3c85053cd0d1f07c5edeb276c03c9c8614e78736626d7024eb6987c24ed), + (0x1b6f5383c5a0ae5bf457e1c8e17a933e892464d33fef9e9262411e01c117d87e, 0x0c552b960e8ce365b5f2302bcc0b7ce5cdf964e6036602cfc859c8769184f619), + (0x3fa4b5cc33e30de3ac7342c84f47f4fffe7ae77dda1689c2f08050d0ab743cb1, 0x327663e39b128ec28c94486b1e5d4429000626f65230ed572c66f80406a42176), + (0x2184a7d65b5000cc5c5f178c2f4ab5b11a67fdc626771c29ade508020c8da032, 0x34c98ee1f6dfa6c1e8cd915d1efeb484206e13e5e32e13118925913568e620b7), (0x1e355d783cffccafc120f462461fb312773442762383ac444009653f3d8d4be6, 0x3c60e17b18492aa2c41798b409d2bcc1857ca57ee9d2fb0001584cedc8e141d6), - (0x32059fe4e96eb002f24f6e6090014f7b3baf23946cc31a11341543a5a184903c, 0x3793fd512a65c7aa7c17a42e855eb8be26aa644165a9bc963c368baf0e5cce9d), (0x0a6fe1cc1ce659681079768ca8ff94d82c7d51ef39cd99b738b144de3a3027f6, 0x30cfc2f4e0ec95f623199970d8b762647ad2d7c3591a20781ee8187702babe5f), (0x00d87a2c430f1db50a63f18f8cf8807f4f70d3acb940d4130ba6811f8ba2d479, 0x13d5742320e1b2cecda6073b7f2bf5816b9067453deeaa829f356a65ef5621b2), (0x3118979ade023f3977d034f86eed6506d7e0586ead81f80bc5ca01a7660ee0c9, 0x30f6731193d5c786cf61b05523c05e2664a066c2d39a685588f02883057320ad), From 13faedc7cc5595dc25625323e705bce9a2a51464 Mon Sep 17 00:00:00 2001 From: therealyingtong Date: Tue, 30 Nov 2021 13:29:52 -0500 Subject: [PATCH 21/59] chip::add_incomplete: Refactor add_incomplete::Config. This is also used in mul_fixed. --- src/circuit/gadget/ecc/chip.rs | 15 +++---- src/circuit/gadget/ecc/chip/add_incomplete.rs | 43 ++++++++++++------- src/circuit/gadget/ecc/chip/mul_fixed.rs | 2 +- 3 files changed, 35 insertions(+), 25 deletions(-) diff --git a/src/circuit/gadget/ecc/chip.rs b/src/circuit/gadget/ecc/chip.rs index 956330b4..a12b7030 100644 --- a/src/circuit/gadget/ecc/chip.rs +++ b/src/circuit/gadget/ecc/chip.rs @@ -139,7 +139,7 @@ pub struct EccConfig { pub fixed_z: Column, /// Incomplete addition - pub q_add_incomplete: Selector, + add_incomplete: add_incomplete::Config, /// Complete addition pub q_add: Selector, @@ -249,12 +249,15 @@ impl EccChip { // Create witness point gate let witness_point = witness_point::Config::configure(meta, advices[0], advices[1]); + // Create incomplete point addition gate + let add_incomplete = + add_incomplete::Config::configure(meta, advices[0], advices[1], advices[2], advices[3]); let config = EccConfig { advices, lagrange_coeffs, fixed_z: meta.fixed_column(), - q_add_incomplete: meta.selector(), + add_incomplete, q_add: meta.selector(), q_mul_hi: (meta.selector(), meta.selector(), meta.selector()), q_mul_lo: (meta.selector(), meta.selector(), meta.selector()), @@ -270,12 +273,6 @@ impl EccChip { running_sum_config, }; - // Create incomplete point addition gate - { - let config: add_incomplete::Config = (&config).into(); - config.create_gate(meta); - } - // Create complete point addition gate { let add_config: add::Config = (&config).into(); @@ -432,7 +429,7 @@ impl EccInstructions for EccChip { a: &Self::NonIdentityPoint, b: &Self::NonIdentityPoint, ) -> Result { - let config: add_incomplete::Config = self.config().into(); + let config = self.config().add_incomplete; layouter.assign_region( || "incomplete point addition", |mut region| config.assign_region(a, b, 0, &mut region), diff --git a/src/circuit/gadget/ecc/chip/add_incomplete.rs b/src/circuit/gadget/ecc/chip/add_incomplete.rs index a5da1875..30b74e0d 100644 --- a/src/circuit/gadget/ecc/chip/add_incomplete.rs +++ b/src/circuit/gadget/ecc/chip/add_incomplete.rs @@ -1,6 +1,6 @@ use std::{array, collections::HashSet}; -use super::{copy, CellValue, EccConfig, NonIdentityEccPoint, Var}; +use super::{copy, CellValue, NonIdentityEccPoint, Var}; use group::Curve; use halo2::{ circuit::Region, @@ -9,7 +9,7 @@ use halo2::{ }; use pasta_curves::{arithmetic::CurveAffine, pallas}; -#[derive(Clone, Debug)] +#[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct Config { q_add_incomplete: Selector, // x-coordinate of P in P + Q = R @@ -22,24 +22,37 @@ pub struct Config { pub y_qr: Column, } -impl From<&EccConfig> for Config { - fn from(ecc_config: &EccConfig) -> Self { - Self { - q_add_incomplete: ecc_config.q_add_incomplete, - x_p: ecc_config.advices[0], - y_p: ecc_config.advices[1], - x_qr: ecc_config.advices[2], - y_qr: ecc_config.advices[3], - } - } -} - impl Config { + pub(super) fn configure( + meta: &mut ConstraintSystem, + x_p: Column, + y_p: Column, + x_qr: Column, + y_qr: Column, + ) -> Self { + meta.enable_equality(x_p.into()); + meta.enable_equality(y_p.into()); + meta.enable_equality(x_qr.into()); + meta.enable_equality(y_qr.into()); + + let config = Self { + q_add_incomplete: meta.selector(), + x_p, + y_p, + x_qr, + y_qr, + }; + + config.create_gate(meta); + + config + } + pub(crate) fn advice_columns(&self) -> HashSet> { core::array::IntoIter::new([self.x_p, self.y_p, self.x_qr, self.y_qr]).collect() } - pub(super) fn create_gate(&self, meta: &mut ConstraintSystem) { + fn create_gate(&self, meta: &mut ConstraintSystem) { meta.create_gate("incomplete addition gates", |meta| { let q_add_incomplete = meta.query_selector(self.q_add_incomplete); let x_p = meta.query_advice(self.x_p, Rotation::cur()); diff --git a/src/circuit/gadget/ecc/chip/mul_fixed.rs b/src/circuit/gadget/ecc/chip/mul_fixed.rs index 87c2e376..bb2b87a8 100644 --- a/src/circuit/gadget/ecc/chip/mul_fixed.rs +++ b/src/circuit/gadget/ecc/chip/mul_fixed.rs @@ -108,7 +108,7 @@ impl From<&EccConfig> for Config { window: ecc_config.advices[4], u: ecc_config.advices[5], add_config: ecc_config.into(), - add_incomplete_config: ecc_config.into(), + add_incomplete_config: ecc_config.add_incomplete, }; // Check relationships between this config and `add_config`. From 4fe6fb8bf25f43adc5335f0fd68e8ea61c3c5954 Mon Sep 17 00:00:00 2001 From: therealyingtong Date: Tue, 30 Nov 2021 13:41:02 -0500 Subject: [PATCH 22/59] chip::add: Refactor add::Config. This is also used in mul and mul_fixed. --- src/circuit/gadget/ecc/chip.rs | 24 ++++----- src/circuit/gadget/ecc/chip/add.rs | 59 ++++++++++++++------- src/circuit/gadget/ecc/chip/mul.rs | 2 +- src/circuit/gadget/ecc/chip/mul/complete.rs | 2 +- src/circuit/gadget/ecc/chip/mul_fixed.rs | 2 +- 5 files changed, 51 insertions(+), 38 deletions(-) diff --git a/src/circuit/gadget/ecc/chip.rs b/src/circuit/gadget/ecc/chip.rs index a12b7030..9c875abf 100644 --- a/src/circuit/gadget/ecc/chip.rs +++ b/src/circuit/gadget/ecc/chip.rs @@ -142,7 +142,7 @@ pub struct EccConfig { add_incomplete: add_incomplete::Config, /// Complete addition - pub q_add: Selector, + add: add::Config, /// Variable-base scalar multiplication (hi half) pub q_mul_hi: (Selector, Selector, Selector), @@ -214,12 +214,6 @@ impl EccChip { ) -> >::Config { // The following columns need to be equality-enabled for their use in sub-configs: // - // add::Config and add_incomplete::Config: - // - advices[0]: x_p, - // - advices[1]: y_p, - // - advices[2]: x_qr, - // - advices[3]: y_qr, - // // mul_fixed::Config: // - advices[4]: window // - advices[5]: u @@ -253,12 +247,18 @@ impl EccChip { let add_incomplete = add_incomplete::Config::configure(meta, advices[0], advices[1], advices[2], advices[3]); + // Create complete point addition gate + let add = add::Config::configure( + meta, advices[0], advices[1], advices[2], advices[3], advices[4], advices[5], + advices[6], advices[7], advices[8], + ); + let config = EccConfig { advices, lagrange_coeffs, fixed_z: meta.fixed_column(), add_incomplete, - q_add: meta.selector(), + add, q_mul_hi: (meta.selector(), meta.selector(), meta.selector()), q_mul_lo: (meta.selector(), meta.selector(), meta.selector()), q_mul_decompose_var: meta.selector(), @@ -273,12 +273,6 @@ impl EccChip { running_sum_config, }; - // Create complete point addition gate - { - let add_config: add::Config = (&config).into(); - add_config.create_gate(meta); - } - // Create variable-base scalar mul gates { let mul_config: mul::Config = (&config).into(); @@ -442,7 +436,7 @@ impl EccInstructions for EccChip { a: &A, b: &B, ) -> Result { - let config: add::Config = self.config().into(); + let config = self.config().add; layouter.assign_region( || "complete point addition", |mut region| { diff --git a/src/circuit/gadget/ecc/chip/add.rs b/src/circuit/gadget/ecc/chip/add.rs index 3fdf7732..9e10d02c 100644 --- a/src/circuit/gadget/ecc/chip/add.rs +++ b/src/circuit/gadget/ecc/chip/add.rs @@ -1,6 +1,6 @@ use std::array; -use super::{copy, CellValue, EccConfig, EccPoint, Var}; +use super::{copy, CellValue, EccPoint, Var}; use ff::{BatchInvert, Field}; use halo2::{ circuit::Region, @@ -10,7 +10,7 @@ use halo2::{ use pasta_curves::{arithmetic::FieldExt, pallas}; use std::collections::HashSet; -#[derive(Clone, Debug)] +#[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct Config { q_add: Selector, // lambda @@ -33,24 +33,43 @@ pub struct Config { delta: Column, } -impl From<&EccConfig> for Config { - fn from(ecc_config: &EccConfig) -> Self { - Self { - q_add: ecc_config.q_add, - x_p: ecc_config.advices[0], - y_p: ecc_config.advices[1], - x_qr: ecc_config.advices[2], - y_qr: ecc_config.advices[3], - lambda: ecc_config.advices[4], - alpha: ecc_config.advices[5], - beta: ecc_config.advices[6], - gamma: ecc_config.advices[7], - delta: ecc_config.advices[8], - } - } -} - impl Config { + #[allow(clippy::too_many_arguments)] + pub(super) fn configure( + meta: &mut ConstraintSystem, + x_p: Column, + y_p: Column, + x_qr: Column, + y_qr: Column, + lambda: Column, + alpha: Column, + beta: Column, + gamma: Column, + delta: Column, + ) -> Self { + meta.enable_equality(x_p.into()); + meta.enable_equality(y_p.into()); + meta.enable_equality(x_qr.into()); + meta.enable_equality(y_qr.into()); + + let config = Self { + q_add: meta.selector(), + x_p, + y_p, + x_qr, + y_qr, + lambda, + alpha, + beta, + gamma, + delta, + }; + + config.create_gate(meta); + + config + } + pub(crate) fn advice_columns(&self) -> HashSet> { core::array::IntoIter::new([ self.x_p, @@ -70,7 +89,7 @@ impl Config { core::array::IntoIter::new([self.x_qr, self.y_qr]).collect() } - pub(crate) fn create_gate(&self, meta: &mut ConstraintSystem) { + fn create_gate(&self, meta: &mut ConstraintSystem) { meta.create_gate("complete addition gates", |meta| { let q_add = meta.query_selector(self.q_add); let x_p = meta.query_advice(self.x_p, Rotation::cur()); diff --git a/src/circuit/gadget/ecc/chip/mul.rs b/src/circuit/gadget/ecc/chip/mul.rs index d3043995..329cd25d 100644 --- a/src/circuit/gadget/ecc/chip/mul.rs +++ b/src/circuit/gadget/ecc/chip/mul.rs @@ -61,7 +61,7 @@ impl From<&EccConfig> for Config { fn from(ecc_config: &EccConfig) -> Self { let config = Self { q_mul_lsb: ecc_config.q_mul_lsb, - add_config: ecc_config.into(), + add_config: ecc_config.add, hi_config: ecc_config.into(), lo_config: ecc_config.into(), complete_config: ecc_config.into(), diff --git a/src/circuit/gadget/ecc/chip/mul/complete.rs b/src/circuit/gadget/ecc/chip/mul/complete.rs index 4c88cef9..585261a2 100644 --- a/src/circuit/gadget/ecc/chip/mul/complete.rs +++ b/src/circuit/gadget/ecc/chip/mul/complete.rs @@ -24,7 +24,7 @@ impl From<&EccConfig> for Config { let config = Self { q_mul_decompose_var: ecc_config.q_mul_decompose_var, z_complete: ecc_config.advices[9], - add_config: ecc_config.into(), + add_config: ecc_config.add, }; let add_config_advices = config.add_config.advice_columns(); diff --git a/src/circuit/gadget/ecc/chip/mul_fixed.rs b/src/circuit/gadget/ecc/chip/mul_fixed.rs index bb2b87a8..e4e7fb01 100644 --- a/src/circuit/gadget/ecc/chip/mul_fixed.rs +++ b/src/circuit/gadget/ecc/chip/mul_fixed.rs @@ -107,7 +107,7 @@ impl From<&EccConfig> for Config { y_p: ecc_config.advices[1], window: ecc_config.advices[4], u: ecc_config.advices[5], - add_config: ecc_config.into(), + add_config: ecc_config.add, add_incomplete_config: ecc_config.add_incomplete, }; From 2ec480ef6beedb9c29d4c1e562ebdb52e09a5c60 Mon Sep 17 00:00:00 2001 From: therealyingtong Date: Tue, 30 Nov 2021 14:31:42 -0500 Subject: [PATCH 23/59] utilities::lookup_range_check: Derive Copy for LookupRangeCheckConfig. --- src/circuit.rs | 4 ++-- src/circuit/gadget/ecc/chip/mul/overflow.rs | 2 +- src/circuit/gadget/ecc/chip/mul_fixed/base_field_elem.rs | 2 +- src/circuit/gadget/sinsemilla.rs | 5 ++--- src/circuit/gadget/sinsemilla/commit_ivk.rs | 2 +- src/circuit/gadget/sinsemilla/merkle.rs | 2 +- src/circuit/gadget/sinsemilla/note_commit.rs | 2 +- src/circuit/gadget/utilities/lookup_range_check.rs | 2 +- 8 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/circuit.rs b/src/circuit.rs index f1b741dd..931d221c 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -236,7 +236,7 @@ impl plonk::Circuit for Circuit { // Configuration for curve point operations. // This uses 10 advice columns and spans the whole circuit. - let ecc_config = EccChip::configure(meta, advices, lagrange_coeffs, range_check.clone()); + let ecc_config = EccChip::configure(meta, advices, lagrange_coeffs, range_check); // Configuration for the Poseidon hash. let poseidon_config = PoseidonChip::configure( @@ -261,7 +261,7 @@ impl plonk::Circuit for Circuit { advices[6], lagrange_coeffs[0], lookup, - range_check.clone(), + range_check, ); let merkle_config_1 = MerkleChip::configure(meta, sinsemilla_config_1.clone()); diff --git a/src/circuit/gadget/ecc/chip/mul/overflow.rs b/src/circuit/gadget/ecc/chip/mul/overflow.rs index 1a2acf3e..8618f97f 100644 --- a/src/circuit/gadget/ecc/chip/mul/overflow.rs +++ b/src/circuit/gadget/ecc/chip/mul/overflow.rs @@ -28,7 +28,7 @@ impl From<&EccConfig> for Config { fn from(ecc_config: &EccConfig) -> Self { Self { q_mul_overflow: ecc_config.q_mul_overflow, - lookup_config: ecc_config.lookup_config.clone(), + lookup_config: ecc_config.lookup_config, // Use advice columns that don't conflict with the either the incomplete // additions in fixed-base scalar mul, or the lookup range checks. advices: [ diff --git a/src/circuit/gadget/ecc/chip/mul_fixed/base_field_elem.rs b/src/circuit/gadget/ecc/chip/mul_fixed/base_field_elem.rs index 4b24d00c..63895545 100644 --- a/src/circuit/gadget/ecc/chip/mul_fixed/base_field_elem.rs +++ b/src/circuit/gadget/ecc/chip/mul_fixed/base_field_elem.rs @@ -33,7 +33,7 @@ impl From<&EccConfig> for Config { q_mul_fixed_running_sum: config.q_mul_fixed_running_sum, q_mul_fixed_base_field: config.q_mul_fixed_base_field, canon_advices: [config.advices[6], config.advices[7], config.advices[8]], - lookup_config: config.lookup_config.clone(), + lookup_config: config.lookup_config, running_sum_config: config.running_sum_config.clone(), super_config: config.into(), }; diff --git a/src/circuit/gadget/sinsemilla.rs b/src/circuit/gadget/sinsemilla.rs index de562d8d..91fe3381 100644 --- a/src/circuit/gadget/sinsemilla.rs +++ b/src/circuit/gadget/sinsemilla.rs @@ -487,8 +487,7 @@ mod tests { let range_check = LookupRangeCheckConfig::configure(meta, advices[9], table_idx); - let ecc_config = - EccChip::configure(meta, advices, lagrange_coeffs, range_check.clone()); + let ecc_config = EccChip::configure(meta, advices, lagrange_coeffs, range_check); let config1 = SinsemillaChip::configure( meta, @@ -496,7 +495,7 @@ mod tests { advices[2], lagrange_coeffs[0], lookup, - range_check.clone(), + range_check, ); let config2 = SinsemillaChip::configure( meta, diff --git a/src/circuit/gadget/sinsemilla/commit_ivk.rs b/src/circuit/gadget/sinsemilla/commit_ivk.rs index e691031b..dd3a8be3 100644 --- a/src/circuit/gadget/sinsemilla/commit_ivk.rs +++ b/src/circuit/gadget/sinsemilla/commit_ivk.rs @@ -722,7 +722,7 @@ mod tests { advices[2], lagrange_coeffs[0], lookup, - range_check.clone(), + range_check, ); let commit_ivk_config = diff --git a/src/circuit/gadget/sinsemilla/merkle.rs b/src/circuit/gadget/sinsemilla/merkle.rs index d9be7163..a5d24d48 100644 --- a/src/circuit/gadget/sinsemilla/merkle.rs +++ b/src/circuit/gadget/sinsemilla/merkle.rs @@ -210,7 +210,7 @@ pub mod tests { advices[7], fixed_y_q_1, lookup, - range_check.clone(), + range_check, ); let config1 = MerkleChip::configure(meta, sinsemilla_config_1); diff --git a/src/circuit/gadget/sinsemilla/note_commit.rs b/src/circuit/gadget/sinsemilla/note_commit.rs index 12e18cc4..72f4b785 100644 --- a/src/circuit/gadget/sinsemilla/note_commit.rs +++ b/src/circuit/gadget/sinsemilla/note_commit.rs @@ -1528,7 +1528,7 @@ mod tests { advices[2], lagrange_coeffs[0], lookup, - range_check.clone(), + range_check, ); let note_commit_config = NoteCommitConfig::configure(meta, advices, sinsemilla_config); diff --git a/src/circuit/gadget/utilities/lookup_range_check.rs b/src/circuit/gadget/utilities/lookup_range_check.rs index 9379b208..4a2c6d85 100644 --- a/src/circuit/gadget/utilities/lookup_range_check.rs +++ b/src/circuit/gadget/utilities/lookup_range_check.rs @@ -23,7 +23,7 @@ impl std::ops::Deref for RunningSum { } } -#[derive(Eq, PartialEq, Debug, Clone)] +#[derive(Eq, PartialEq, Debug, Clone, Copy)] pub struct LookupRangeCheckConfig { pub q_lookup: Selector, pub q_running: Selector, From 0ede6b230144ec994a4fcbcc24ef5858f7a78084 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Sat, 4 Dec 2021 04:35:33 +0000 Subject: [PATCH 24/59] mul::Config: Reorder gate definitions We are about to extract the sub-configs from mul::Config and refactor them. Doing so would have moved their gate definitions past the one gate that isn't created in a sub-config. Reordering the definitions here will make the subsequent refactor diffs simpler to review. --- src/circuit/gadget/ecc/chip/mul.rs | 10 +- src/circuit_description | 846 ++++++++++++++--------------- 2 files changed, 428 insertions(+), 428 deletions(-) diff --git a/src/circuit/gadget/ecc/chip/mul.rs b/src/circuit/gadget/ecc/chip/mul.rs index 329cd25d..e2f02445 100644 --- a/src/circuit/gadget/ecc/chip/mul.rs +++ b/src/circuit/gadget/ecc/chip/mul.rs @@ -98,6 +98,11 @@ impl From<&EccConfig> for Config { impl Config { pub(super) fn create_gate(&self, meta: &mut ConstraintSystem) { + self.hi_config.create_gate(meta); + self.lo_config.create_gate(meta); + self.complete_config.create_gate(meta); + self.overflow_config.create_gate(meta); + // If `lsb` is 0, (x, y) = (x_p, -y_p). If `lsb` is 1, (x, y) = (0,0). meta.create_gate("LSB check", |meta| { let q_mul_lsb = meta.query_selector(self.q_mul_lsb); @@ -127,11 +132,6 @@ impl Config { ]) .map(move |(name, poly)| (name, q_mul_lsb.clone() * poly)) }); - - self.hi_config.create_gate(meta); - self.lo_config.create_gate(meta); - self.complete_config.create_gate(meta); - self.overflow_config.create_gate(meta); } pub(super) fn assign( diff --git a/src/circuit_description b/src/circuit_description index 8b6cb01d..46141a26 100644 --- a/src/circuit_description +++ b/src/circuit_description @@ -3319,386 +3319,6 @@ PinnedVerificationKey { }, ), ), - Product( - Product( - Product( - Product( - Fixed { - query_index: 22, - column_index: 22, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 22, - column_index: 22, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, - ), - Negated( - Fixed { - query_index: 22, - column_index: 22, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, - ), - Negated( - Fixed { - query_index: 22, - column_index: 22, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Product( - Sum( - Advice { - query_index: 10, - column_index: 9, - rotation: Rotation( - 1, - ), - }, - Negated( - Scaled( - Advice { - query_index: 9, - column_index: 9, - rotation: Rotation( - 0, - ), - }, - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Sum( - Advice { - query_index: 10, - column_index: 9, - rotation: Rotation( - 1, - ), - }, - Negated( - Scaled( - Advice { - query_index: 9, - column_index: 9, - rotation: Rotation( - 0, - ), - }, - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - ), - ), - ), - ), - ), - ), - Product( - Product( - Product( - Product( - Fixed { - query_index: 22, - column_index: 22, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 22, - column_index: 22, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, - ), - Negated( - Fixed { - query_index: 22, - column_index: 22, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, - ), - Negated( - Fixed { - query_index: 22, - column_index: 22, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Product( - Sum( - Advice { - query_index: 10, - column_index: 9, - rotation: Rotation( - 1, - ), - }, - Negated( - Scaled( - Advice { - query_index: 9, - column_index: 9, - rotation: Rotation( - 0, - ), - }, - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - ), - ), - Advice { - query_index: 0, - column_index: 0, - rotation: Rotation( - 0, - ), - }, - ), - Product( - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Sum( - Advice { - query_index: 10, - column_index: 9, - rotation: Rotation( - 1, - ), - }, - Negated( - Scaled( - Advice { - query_index: 9, - column_index: 9, - rotation: Rotation( - 0, - ), - }, - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - ), - ), - ), - ), - Sum( - Advice { - query_index: 0, - column_index: 0, - rotation: Rotation( - 0, - ), - }, - Negated( - Advice { - query_index: 15, - column_index: 0, - rotation: Rotation( - 1, - ), - }, - ), - ), - ), - ), - ), - Product( - Product( - Product( - Product( - Fixed { - query_index: 22, - column_index: 22, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 22, - column_index: 22, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, - ), - Negated( - Fixed { - query_index: 22, - column_index: 22, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, - ), - Negated( - Fixed { - query_index: 22, - column_index: 22, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Product( - Sum( - Advice { - query_index: 10, - column_index: 9, - rotation: Rotation( - 1, - ), - }, - Negated( - Scaled( - Advice { - query_index: 9, - column_index: 9, - rotation: Rotation( - 0, - ), - }, - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - ), - ), - Advice { - query_index: 1, - column_index: 1, - rotation: Rotation( - 0, - ), - }, - ), - Product( - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Sum( - Advice { - query_index: 10, - column_index: 9, - rotation: Rotation( - 1, - ), - }, - Negated( - Scaled( - Advice { - query_index: 9, - column_index: 9, - rotation: Rotation( - 0, - ), - }, - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - ), - ), - ), - ), - Sum( - Advice { - query_index: 1, - column_index: 1, - rotation: Rotation( - 0, - ), - }, - Advice { - query_index: 16, - column_index: 1, - rotation: Rotation( - 1, - ), - }, - ), - ), - ), - ), Product( Product( Product( @@ -3807,7 +3427,7 @@ PinnedVerificationKey { ), }, Advice { - query_index: 17, + query_index: 15, column_index: 5, rotation: Rotation( 1, @@ -3853,7 +3473,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 15, + query_index: 16, column_index: 0, rotation: Rotation( 1, @@ -3967,7 +3587,7 @@ PinnedVerificationKey { }, Negated( Advice { - query_index: 15, + query_index: 16, column_index: 0, rotation: Rotation( 1, @@ -4074,7 +3694,7 @@ PinnedVerificationKey { }, Negated( Advice { - query_index: 16, + query_index: 17, column_index: 1, rotation: Rotation( 1, @@ -4826,7 +4446,7 @@ PinnedVerificationKey { ), }, Advice { - query_index: 17, + query_index: 15, column_index: 5, rotation: Rotation( 1, @@ -4872,7 +4492,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 15, + query_index: 16, column_index: 0, rotation: Rotation( 1, @@ -5768,7 +5388,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 15, + query_index: 16, column_index: 0, rotation: Rotation( 1, @@ -5866,7 +5486,7 @@ PinnedVerificationKey { }, Negated( Advice { - query_index: 15, + query_index: 16, column_index: 0, rotation: Rotation( 1, @@ -5957,7 +5577,7 @@ PinnedVerificationKey { }, Negated( Advice { - query_index: 16, + query_index: 17, column_index: 1, rotation: Rotation( 1, @@ -6691,7 +6311,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 15, + query_index: 16, column_index: 0, rotation: Rotation( 1, @@ -8193,6 +7813,386 @@ PinnedVerificationKey { }, ), ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Advice { + query_index: 10, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 10, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Sum( + Advice { + query_index: 10, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 10, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + ), + ), + Sum( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 16, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Sum( + Advice { + query_index: 10, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 10, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + ), + ), + Sum( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 17, + column_index: 1, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), Product( Fixed { query_index: 19, @@ -13093,7 +13093,7 @@ PinnedVerificationKey { Sum( Sum( Advice { - query_index: 15, + query_index: 16, column_index: 0, rotation: Rotation( 1, @@ -13179,7 +13179,7 @@ PinnedVerificationKey { }, Negated( Advice { - query_index: 15, + query_index: 16, column_index: 0, rotation: Rotation( 1, @@ -13311,7 +13311,7 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 15, + query_index: 16, column_index: 0, rotation: Rotation( 1, @@ -13338,7 +13338,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 15, + query_index: 16, column_index: 0, rotation: Rotation( 1, @@ -13348,7 +13348,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 16, + query_index: 17, column_index: 1, rotation: Rotation( 1, @@ -13798,7 +13798,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 15, + query_index: 16, column_index: 0, rotation: Rotation( 1, @@ -13910,7 +13910,7 @@ PinnedVerificationKey { Sum( Sum( Advice { - query_index: 15, + query_index: 16, column_index: 0, rotation: Rotation( 1, @@ -13929,7 +13929,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 16, + query_index: 17, column_index: 1, rotation: Rotation( 1, @@ -14173,7 +14173,7 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 16, + query_index: 17, column_index: 1, rotation: Rotation( 1, @@ -14401,7 +14401,7 @@ PinnedVerificationKey { Sum( Sum( Advice { - query_index: 17, + query_index: 15, column_index: 5, rotation: Rotation( 1, @@ -14487,7 +14487,7 @@ PinnedVerificationKey { }, Negated( Advice { - query_index: 17, + query_index: 15, column_index: 5, rotation: Rotation( 1, @@ -14619,7 +14619,7 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 17, + query_index: 15, column_index: 5, rotation: Rotation( 1, @@ -14646,7 +14646,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 17, + query_index: 15, column_index: 5, rotation: Rotation( 1, @@ -15266,7 +15266,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 17, + query_index: 15, column_index: 5, rotation: Rotation( 1, @@ -15394,7 +15394,7 @@ PinnedVerificationKey { Sum( Sum( Advice { - query_index: 17, + query_index: 15, column_index: 5, rotation: Rotation( 1, @@ -16424,7 +16424,7 @@ PinnedVerificationKey { }, Scaled( Advice { - query_index: 16, + query_index: 17, column_index: 1, rotation: Rotation( 1, @@ -16457,7 +16457,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 15, + query_index: 16, column_index: 0, rotation: Rotation( 1, @@ -17211,7 +17211,7 @@ PinnedVerificationKey { }, Scaled( Advice { - query_index: 16, + query_index: 17, column_index: 1, rotation: Rotation( 1, @@ -21504,7 +21504,7 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 17, + query_index: 15, column_index: 5, rotation: Rotation( 1, @@ -21661,7 +21661,7 @@ PinnedVerificationKey { Sum( Sum( Advice { - query_index: 17, + query_index: 15, column_index: 5, rotation: Rotation( 1, @@ -21800,7 +21800,7 @@ PinnedVerificationKey { Sum( Sum( Advice { - query_index: 17, + query_index: 15, column_index: 5, rotation: Rotation( 1, @@ -26460,7 +26460,7 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 17, + query_index: 15, column_index: 5, rotation: Rotation( 1, @@ -26617,7 +26617,7 @@ PinnedVerificationKey { Sum( Sum( Advice { - query_index: 17, + query_index: 15, column_index: 5, rotation: Rotation( 1, @@ -26756,7 +26756,7 @@ PinnedVerificationKey { Sum( Sum( Advice { - query_index: 17, + query_index: 15, column_index: 5, rotation: Rotation( 1, @@ -27283,6 +27283,15 @@ PinnedVerificationKey { 1, ), ), + ( + Column { + index: 5, + column_type: Advice, + }, + Rotation( + 1, + ), + ), ( Column { index: 0, @@ -27301,15 +27310,6 @@ PinnedVerificationKey { 1, ), ), - ( - Column { - index: 5, - column_type: Advice, - }, - Rotation( - 1, - ), - ), ( Column { index: 7, From 22f57005a98035807e239e4bc57f477f8c932d07 Mon Sep 17 00:00:00 2001 From: therealyingtong Date: Tue, 30 Nov 2021 15:59:29 -0500 Subject: [PATCH 25/59] mul::incomplete: Refactor incomplete::Config. This is only used in chip::mul::Config. In a subsequent commit, this will be configured from mul::Config instead of from ecc::chip::Config. This commit does not result in circuit changes. --- src/circuit/gadget/ecc/chip.rs | 17 +++- src/circuit/gadget/ecc/chip/mul.rs | 31 ++++-- src/circuit/gadget/ecc/chip/mul/incomplete.rs | 94 +++++++------------ 3 files changed, 67 insertions(+), 75 deletions(-) diff --git a/src/circuit/gadget/ecc/chip.rs b/src/circuit/gadget/ecc/chip.rs index 9c875abf..0ce5f6bd 100644 --- a/src/circuit/gadget/ecc/chip.rs +++ b/src/circuit/gadget/ecc/chip.rs @@ -145,9 +145,9 @@ pub struct EccConfig { add: add::Config, /// Variable-base scalar multiplication (hi half) - pub q_mul_hi: (Selector, Selector, Selector), + mul_hi: mul::incomplete::Config<{ mul::INCOMPLETE_HI_LEN }>, /// Variable-base scalar multiplication (lo half) - pub q_mul_lo: (Selector, Selector, Selector), + mul_lo: mul::incomplete::Config<{ mul::INCOMPLETE_LO_LEN }>, /// Selector used to enforce boolean decomposition in variable-base scalar mul pub q_mul_decompose_var: Selector, /// Selector used to enforce switching logic on LSB in variable-base scalar mul @@ -253,14 +253,23 @@ impl EccChip { advices[6], advices[7], advices[8], ); + // Components of mul::Config + // TODO: Move this into mul::Config. + let mul_hi = mul::incomplete::Config::configure( + meta, advices[9], advices[3], advices[0], advices[1], advices[4], advices[5], + ); + let mul_lo = mul::incomplete::Config::configure( + meta, advices[6], advices[7], advices[0], advices[1], advices[8], advices[2], + ); + let config = EccConfig { advices, lagrange_coeffs, fixed_z: meta.fixed_column(), add_incomplete, add, - q_mul_hi: (meta.selector(), meta.selector(), meta.selector()), - q_mul_lo: (meta.selector(), meta.selector(), meta.selector()), + mul_hi, + mul_lo, q_mul_decompose_var: meta.selector(), q_mul_overflow: meta.selector(), q_mul_lsb: meta.selector(), diff --git a/src/circuit/gadget/ecc/chip/mul.rs b/src/circuit/gadget/ecc/chip/mul.rs index e2f02445..a95e0831 100644 --- a/src/circuit/gadget/ecc/chip/mul.rs +++ b/src/circuit/gadget/ecc/chip/mul.rs @@ -17,7 +17,8 @@ use halo2::{ use pasta_curves::pallas; mod complete; -mod incomplete; +// TODO: Undo this pub(crate). +pub(crate) mod incomplete; mod overflow; /// Number of bits for which complete addition needs to be used in variable-base @@ -33,10 +34,12 @@ const INCOMPLETE_RANGE: Range = 0..INCOMPLETE_LEN; // (It is a coincidence that k_{130} matches the boundary of the // overflow check described in [the book](https://zcash.github.io/halo2/design/gadgets/ecc/var-base-scalar-mul.html#overflow-check).) const INCOMPLETE_HI_RANGE: Range = 0..(INCOMPLETE_LEN / 2); +pub const INCOMPLETE_HI_LEN: usize = INCOMPLETE_LEN / 2; // Bits k_{254} to k_{4} inclusive are used in incomplete addition. // The `lo` half is k_{129} to k_{4} inclusive (length 126 bits). const INCOMPLETE_LO_RANGE: Range = (INCOMPLETE_LEN / 2)..INCOMPLETE_LEN; +pub const INCOMPLETE_LO_LEN: usize = (INCOMPLETE_LEN / 2) + 1; // Bits k_{3} to k_{1} inclusive are used in complete addition. // Bit k_{0} is handled separately. @@ -48,9 +51,9 @@ pub struct Config { // Configuration used in complete addition add_config: add::Config, // Configuration used for `hi` bits of the scalar - hi_config: incomplete::HiConfig, + hi_config: incomplete::Config, // Configuration used for `lo` bits of the scalar - lo_config: incomplete::LoConfig, + lo_config: incomplete::Config, // Configuration used for complete addition part of double-and-add algorithm complete_config: complete::Config, // Configuration used to check for overflow @@ -62,8 +65,8 @@ impl From<&EccConfig> for Config { let config = Self { q_mul_lsb: ecc_config.q_mul_lsb, add_config: ecc_config.add, - hi_config: ecc_config.into(), - lo_config: ecc_config.into(), + hi_config: ecc_config.mul_hi, + lo_config: ecc_config.mul_lo, complete_config: ecc_config.into(), overflow_config: ecc_config.into(), }; @@ -81,13 +84,23 @@ impl From<&EccConfig> for Config { // z and lambda1 are assigned on the same row as the add_config output. // Therefore, z and lambda1 must not overlap with add_config.x_qr, add_config.y_qr. let add_config_outputs = config.add_config.output_columns(); - for config in [&(*config.hi_config), &(*config.lo_config)].iter() { + { assert!( - !add_config_outputs.contains(&config.z), + !add_config_outputs.contains(&config.hi_config.z), "incomplete config z cannot overlap with complete addition columns." ); assert!( - !add_config_outputs.contains(&config.lambda1), + !add_config_outputs.contains(&config.hi_config.lambda1), + "incomplete config lambda1 cannot overlap with complete addition columns." + ); + } + { + assert!( + !add_config_outputs.contains(&config.lo_config.z), + "incomplete config z cannot overlap with complete addition columns." + ); + assert!( + !add_config_outputs.contains(&config.lo_config.lambda1), "incomplete config lambda1 cannot overlap with complete addition columns." ); } @@ -98,8 +111,6 @@ impl From<&EccConfig> for Config { impl Config { pub(super) fn create_gate(&self, meta: &mut ConstraintSystem) { - self.hi_config.create_gate(meta); - self.lo_config.create_gate(meta); self.complete_config.create_gate(meta); self.overflow_config.create_gate(meta); diff --git a/src/circuit/gadget/ecc/chip/mul/incomplete.rs b/src/circuit/gadget/ecc/chip/mul/incomplete.rs index 4ddac353..63e6919d 100644 --- a/src/circuit/gadget/ecc/chip/mul/incomplete.rs +++ b/src/circuit/gadget/ecc/chip/mul/incomplete.rs @@ -1,7 +1,5 @@ -use std::ops::Deref; - -use super::super::{copy, CellValue, EccConfig, NonIdentityEccPoint, Var}; -use super::{INCOMPLETE_HI_RANGE, INCOMPLETE_LO_RANGE, X, Y, Z}; +use super::super::{copy, CellValue, NonIdentityEccPoint, Var}; +use super::{X, Y, Z}; use crate::circuit::gadget::utilities::bool_check; use ff::Field; use halo2::{ @@ -12,10 +10,8 @@ use halo2::{ use pasta_curves::{arithmetic::FieldExt, pallas}; -#[derive(Copy, Clone)] -pub(super) struct Config { - // Number of bits covered by this incomplete range. - num_bits: usize, +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub(crate) struct Config { // Selectors used to constrain the cells used in incomplete addition. pub(super) q_mul: (Selector, Selector, Selector), // Cumulative sum used to decompose the scalar. @@ -32,61 +28,37 @@ pub(super) struct Config { pub(super) lambda2: Column, } -// Columns used in processing the `hi` bits of the scalar. -// `x_p, y_p` are shared across the `hi` and `lo` halves. -pub(super) struct HiConfig(Config); -impl From<&EccConfig> for HiConfig { - fn from(ecc_config: &EccConfig) -> Self { - let config = Config { - num_bits: INCOMPLETE_HI_RANGE.len(), - q_mul: ecc_config.q_mul_hi, - x_p: ecc_config.advices[0], - y_p: ecc_config.advices[1], - z: ecc_config.advices[9], - x_a: ecc_config.advices[3], - lambda1: ecc_config.advices[4], - lambda2: ecc_config.advices[5], +impl Config { + // TODO: Make this pub(super). + pub(crate) fn configure( + meta: &mut ConstraintSystem, + z: Column, + x_a: Column, + x_p: Column, + y_p: Column, + lambda1: Column, + lambda2: Column, + ) -> Self { + meta.enable_equality(z.into()); + meta.enable_equality(lambda1.into()); + + let config = Self { + q_mul: (meta.selector(), meta.selector(), meta.selector()), + z, + x_a, + x_p, + y_p, + lambda1, + lambda2, }; - Self(config) - } -} -impl Deref for HiConfig { - type Target = Config; - fn deref(&self) -> &Config { - &self.0 - } -} + config.create_gate(meta); -// Columns used in processing the `lo` bits of the scalar. -// `x_p, y_p` are shared across the `hi` and `lo` halves. -pub(super) struct LoConfig(Config); -impl From<&EccConfig> for LoConfig { - fn from(ecc_config: &EccConfig) -> Self { - let config = Config { - num_bits: INCOMPLETE_LO_RANGE.len(), - q_mul: ecc_config.q_mul_lo, - x_p: ecc_config.advices[0], - y_p: ecc_config.advices[1], - z: ecc_config.advices[6], - x_a: ecc_config.advices[7], - lambda1: ecc_config.advices[8], - lambda2: ecc_config.advices[2], - }; - Self(config) + config } -} -impl Deref for LoConfig { - type Target = Config; - fn deref(&self) -> &Config { - &self.0 - } -} - -impl Config { // Gate for incomplete addition part of variable-base scalar multiplication. - pub(super) fn create_gate(&self, meta: &mut ConstraintSystem) { + fn create_gate(&self, meta: &mut ConstraintSystem) { // Closure to compute x_{R,i} = λ_{1,i}^2 - x_{A,i} - x_{P,i} let x_r = |meta: &mut VirtualCells, rotation: Rotation| { let x_a = meta.query_advice(self.x_a, rotation); @@ -216,7 +188,7 @@ impl Config { acc: (X, Y, Z), ) -> Result<(X, Y, Vec>), Error> { // Check that we have the correct number of bits for this double-and-add. - assert_eq!(bits.len(), self.num_bits); + assert_eq!(bits.len(), NUM_BITS); // Handle exceptional cases let (x_p, y_p) = (base.x.value(), base.y.value()); @@ -241,12 +213,12 @@ impl Config { let offset = offset + 1; // q_mul_2 = 1 on all rows after offset 0, excluding the last row. - for idx in 0..(self.num_bits - 1) { + for idx in 0..(NUM_BITS - 1) { self.q_mul.1.enable(region, offset + idx)?; } // q_mul_3 = 1 on the last row. - self.q_mul.2.enable(region, offset + self.num_bits - 1)?; + self.q_mul.2.enable(region, offset + NUM_BITS - 1)?; } // Initialise double-and-add @@ -361,7 +333,7 @@ impl Config { let cell = region.assign_advice( || "y_a", self.lambda1, - offset + self.num_bits, + offset + NUM_BITS, || y_a.ok_or(Error::Synthesis), )?; CellValue::new(cell, y_a) From 931d61a8633752f68803c5298e92e5f40f0c0812 Mon Sep 17 00:00:00 2001 From: therealyingtong Date: Tue, 30 Nov 2021 15:00:05 -0500 Subject: [PATCH 26/59] mul::complete: Refactor complete::Config. This is only used in chip::mul::Config. In a subsequent commit, this will be configured from mul::Config instead of from ecc::chip::Config. This commit does not result in circuit changes. --- src/circuit/gadget/ecc/chip.rs | 8 +++--- src/circuit/gadget/ecc/chip/mul.rs | 6 ++--- src/circuit/gadget/ecc/chip/mul/complete.rs | 30 +++++++++++---------- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/circuit/gadget/ecc/chip.rs b/src/circuit/gadget/ecc/chip.rs index 0ce5f6bd..ab02c99a 100644 --- a/src/circuit/gadget/ecc/chip.rs +++ b/src/circuit/gadget/ecc/chip.rs @@ -149,7 +149,7 @@ pub struct EccConfig { /// Variable-base scalar multiplication (lo half) mul_lo: mul::incomplete::Config<{ mul::INCOMPLETE_LO_LEN }>, /// Selector used to enforce boolean decomposition in variable-base scalar mul - pub q_mul_decompose_var: Selector, + pub mul_complete: mul::complete::Config, /// Selector used to enforce switching logic on LSB in variable-base scalar mul pub q_mul_lsb: Selector, /// Variable-base scalar multiplication (overflow check) @@ -228,9 +228,6 @@ impl EccChip { // - advices[4]: lambda1 // - advices[9]: z // - // mul::complete::Config: - // - advices[9]: z_complete - // // TODO: Refactor away from `impl From for _` so that sub-configs can // equality-enable the columns they need to. for column in &advices { @@ -261,6 +258,7 @@ impl EccChip { let mul_lo = mul::incomplete::Config::configure( meta, advices[6], advices[7], advices[0], advices[1], advices[8], advices[2], ); + let mul_complete = mul::complete::Config::configure(meta, advices[9], add); let config = EccConfig { advices, @@ -270,7 +268,7 @@ impl EccChip { add, mul_hi, mul_lo, - q_mul_decompose_var: meta.selector(), + mul_complete, q_mul_overflow: meta.selector(), q_mul_lsb: meta.selector(), q_mul_fixed_full: meta.selector(), diff --git a/src/circuit/gadget/ecc/chip/mul.rs b/src/circuit/gadget/ecc/chip/mul.rs index a95e0831..21dad7b1 100644 --- a/src/circuit/gadget/ecc/chip/mul.rs +++ b/src/circuit/gadget/ecc/chip/mul.rs @@ -16,7 +16,8 @@ use halo2::{ use pasta_curves::pallas; -mod complete; +// TODO: Undo this pub(crate). +pub(crate) mod complete; // TODO: Undo this pub(crate). pub(crate) mod incomplete; mod overflow; @@ -67,7 +68,7 @@ impl From<&EccConfig> for Config { add_config: ecc_config.add, hi_config: ecc_config.mul_hi, lo_config: ecc_config.mul_lo, - complete_config: ecc_config.into(), + complete_config: ecc_config.mul_complete, overflow_config: ecc_config.into(), }; @@ -111,7 +112,6 @@ impl From<&EccConfig> for Config { impl Config { pub(super) fn create_gate(&self, meta: &mut ConstraintSystem) { - self.complete_config.create_gate(meta); self.overflow_config.create_gate(meta); // If `lsb` is 0, (x, y) = (x_p, -y_p). If `lsb` is 1, (x, y) = (0,0). diff --git a/src/circuit/gadget/ecc/chip/mul/complete.rs b/src/circuit/gadget/ecc/chip/mul/complete.rs index 585261a2..5c5ce049 100644 --- a/src/circuit/gadget/ecc/chip/mul/complete.rs +++ b/src/circuit/gadget/ecc/chip/mul/complete.rs @@ -1,4 +1,4 @@ -use super::super::{add, copy, CellValue, EccConfig, EccPoint, Var}; +use super::super::{add, copy, CellValue, EccPoint, Var}; use super::{COMPLETE_RANGE, X, Y, Z}; use crate::circuit::gadget::utilities::{bool_check, ternary}; @@ -10,6 +10,7 @@ use halo2::{ use pasta_curves::{arithmetic::FieldExt, pallas}; +#[derive(Copy, Clone, Debug, Eq, PartialEq)] pub struct Config { // Selector used to constrain the cells used in complete addition. q_mul_decompose_var: Selector, @@ -19,30 +20,31 @@ pub struct Config { add_config: add::Config, } -impl From<&EccConfig> for Config { - fn from(ecc_config: &EccConfig) -> Self { +impl Config { + /// TODO: Make this pub(super). + pub(crate) fn configure( + meta: &mut ConstraintSystem, + z_complete: Column, + add_config: add::Config, + ) -> Self { + meta.enable_equality(z_complete.into()); + let config = Self { - q_mul_decompose_var: ecc_config.q_mul_decompose_var, - z_complete: ecc_config.advices[9], - add_config: ecc_config.add, + q_mul_decompose_var: meta.selector(), + z_complete, + add_config, }; - let add_config_advices = config.add_config.advice_columns(); - assert!( - !add_config_advices.contains(&config.z_complete), - "z_complete cannot overlap with complete addition columns." - ); + config.create_gate(meta); config } -} -impl Config { /// Gate used to check scalar decomposition is correct. /// This is used to check the bits used in complete addition, since the incomplete /// addition gate (controlled by `q_mul`) already checks scalar decomposition for /// the other bits. - pub(super) fn create_gate(&self, meta: &mut ConstraintSystem) { + fn create_gate(&self, meta: &mut ConstraintSystem) { // | y_p | z_complete | // -------------------- // | y_p | z_{i + 1} | From 440cd14dbb68c625f0cd255b83e306117afe87b6 Mon Sep 17 00:00:00 2001 From: therealyingtong Date: Tue, 30 Nov 2021 14:47:47 -0500 Subject: [PATCH 27/59] mul::overflow: Refactor overflow::Config. This is only used in chip::mul::Config. In a subsequent commit, this will be configured from mul::Config instead of from ecc::chip::Config. This commit does not result in circuit changes. --- src/circuit/gadget/ecc/chip.rs | 11 +++--- src/circuit/gadget/ecc/chip/mul.rs | 7 ++-- src/circuit/gadget/ecc/chip/mul/overflow.rs | 42 ++++++++++++--------- 3 files changed, 33 insertions(+), 27 deletions(-) diff --git a/src/circuit/gadget/ecc/chip.rs b/src/circuit/gadget/ecc/chip.rs index ab02c99a..fb8aed3d 100644 --- a/src/circuit/gadget/ecc/chip.rs +++ b/src/circuit/gadget/ecc/chip.rs @@ -16,6 +16,8 @@ use halo2::{ }; use pasta_curves::{arithmetic::CurveAffine, pallas}; +use std::convert::TryInto; + pub(super) mod add; pub(super) mod add_incomplete; pub(super) mod mul; @@ -153,7 +155,7 @@ pub struct EccConfig { /// Selector used to enforce switching logic on LSB in variable-base scalar mul pub q_mul_lsb: Selector, /// Variable-base scalar multiplication (overflow check) - pub q_mul_overflow: Selector, + pub mul_overflow: mul::overflow::Config, /// Fixed-base full-width scalar multiplication pub q_mul_fixed_full: Selector, @@ -221,9 +223,6 @@ impl EccChip { // mul_fixed::base_field_element::Config: // - [advices[6], advices[7], advices[8]]: canon_advices // - // mul::overflow::Config: - // - [advices[0], advices[1], advices[2]]: advices - // // mul::incomplete::Config // - advices[4]: lambda1 // - advices[9]: z @@ -259,6 +258,8 @@ impl EccChip { meta, advices[6], advices[7], advices[0], advices[1], advices[8], advices[2], ); let mul_complete = mul::complete::Config::configure(meta, advices[9], add); + let mul_overflow = + mul::overflow::Config::configure(meta, range_check, advices[6..9].try_into().unwrap()); let config = EccConfig { advices, @@ -269,7 +270,7 @@ impl EccChip { mul_hi, mul_lo, mul_complete, - q_mul_overflow: meta.selector(), + mul_overflow, q_mul_lsb: meta.selector(), q_mul_fixed_full: meta.selector(), q_mul_fixed_short: meta.selector(), diff --git a/src/circuit/gadget/ecc/chip/mul.rs b/src/circuit/gadget/ecc/chip/mul.rs index 21dad7b1..173d7362 100644 --- a/src/circuit/gadget/ecc/chip/mul.rs +++ b/src/circuit/gadget/ecc/chip/mul.rs @@ -20,7 +20,8 @@ use pasta_curves::pallas; pub(crate) mod complete; // TODO: Undo this pub(crate). pub(crate) mod incomplete; -mod overflow; +// TODO: Undo this pub(crate). +pub(crate) mod overflow; /// Number of bits for which complete addition needs to be used in variable-base /// scalar multiplication @@ -69,7 +70,7 @@ impl From<&EccConfig> for Config { hi_config: ecc_config.mul_hi, lo_config: ecc_config.mul_lo, complete_config: ecc_config.mul_complete, - overflow_config: ecc_config.into(), + overflow_config: ecc_config.mul_overflow, }; assert_eq!( @@ -112,8 +113,6 @@ impl From<&EccConfig> for Config { impl Config { pub(super) fn create_gate(&self, meta: &mut ConstraintSystem) { - self.overflow_config.create_gate(meta); - // If `lsb` is 0, (x, y) = (x_p, -y_p). If `lsb` is 1, (x, y) = (0,0). meta.create_gate("LSB check", |meta| { let q_mul_lsb = meta.query_selector(self.q_mul_lsb); diff --git a/src/circuit/gadget/ecc/chip/mul/overflow.rs b/src/circuit/gadget/ecc/chip/mul/overflow.rs index 8618f97f..4c21975b 100644 --- a/src/circuit/gadget/ecc/chip/mul/overflow.rs +++ b/src/circuit/gadget/ecc/chip/mul/overflow.rs @@ -1,4 +1,4 @@ -use super::super::{copy, CellValue, EccConfig, Var}; +use super::super::{copy, CellValue, Var}; use super::Z; use crate::{ circuit::gadget::utilities::lookup_range_check::LookupRangeCheckConfig, constants::T_Q, @@ -15,6 +15,7 @@ use pasta_curves::{arithmetic::FieldExt, pallas}; use std::iter; +#[derive(Copy, Clone, Debug, Eq, PartialEq)] pub struct Config { // Selector to check z_0 = alpha + t_q (mod p) q_mul_overflow: Selector, @@ -24,24 +25,29 @@ pub struct Config { advices: [Column; 3], } -impl From<&EccConfig> for Config { - fn from(ecc_config: &EccConfig) -> Self { - Self { - q_mul_overflow: ecc_config.q_mul_overflow, - lookup_config: ecc_config.lookup_config, - // Use advice columns that don't conflict with the either the incomplete - // additions in fixed-base scalar mul, or the lookup range checks. - advices: [ - ecc_config.advices[6], - ecc_config.advices[7], - ecc_config.advices[8], - ], - } - } -} - impl Config { - pub(super) fn create_gate(&self, meta: &mut ConstraintSystem) { + // TODO: Make this pub(super). + pub(crate) fn configure( + meta: &mut ConstraintSystem, + lookup_config: LookupRangeCheckConfig, + advices: [Column; 3], + ) -> Self { + for advice in advices.iter() { + meta.enable_equality((*advice).into()); + } + + let config = Self { + q_mul_overflow: meta.selector(), + lookup_config, + advices, + }; + + config.create_gate(meta); + + config + } + + fn create_gate(&self, meta: &mut ConstraintSystem) { meta.create_gate("overflow checks", |meta| { let q_mul_overflow = meta.query_selector(self.q_mul_overflow); From a7dad1d6110cadbc6af5afbfdb90cdc13736a814 Mon Sep 17 00:00:00 2001 From: therealyingtong Date: Tue, 30 Nov 2021 15:41:57 -0500 Subject: [PATCH 28/59] chip::mul: Refactor mul::Config. This commit does not introduce additional circuit changes. --- src/circuit/gadget/ecc/chip.rs | 45 ++----------- src/circuit/gadget/ecc/chip/mul.rs | 65 ++++++++++++------- src/circuit/gadget/ecc/chip/mul/complete.rs | 3 +- src/circuit/gadget/ecc/chip/mul/incomplete.rs | 3 +- src/circuit/gadget/ecc/chip/mul/overflow.rs | 3 +- 5 files changed, 51 insertions(+), 68 deletions(-) diff --git a/src/circuit/gadget/ecc/chip.rs b/src/circuit/gadget/ecc/chip.rs index fb8aed3d..f0d37992 100644 --- a/src/circuit/gadget/ecc/chip.rs +++ b/src/circuit/gadget/ecc/chip.rs @@ -16,8 +16,6 @@ use halo2::{ }; use pasta_curves::{arithmetic::CurveAffine, pallas}; -use std::convert::TryInto; - pub(super) mod add; pub(super) mod add_incomplete; pub(super) mod mul; @@ -146,16 +144,8 @@ pub struct EccConfig { /// Complete addition add: add::Config, - /// Variable-base scalar multiplication (hi half) - mul_hi: mul::incomplete::Config<{ mul::INCOMPLETE_HI_LEN }>, - /// Variable-base scalar multiplication (lo half) - mul_lo: mul::incomplete::Config<{ mul::INCOMPLETE_LO_LEN }>, - /// Selector used to enforce boolean decomposition in variable-base scalar mul - pub mul_complete: mul::complete::Config, - /// Selector used to enforce switching logic on LSB in variable-base scalar mul - pub q_mul_lsb: Selector, - /// Variable-base scalar multiplication (overflow check) - pub mul_overflow: mul::overflow::Config, + /// Variable-base scalar multiplication + mul: mul::Config, /// Fixed-base full-width scalar multiplication pub q_mul_fixed_full: Selector, @@ -223,10 +213,6 @@ impl EccChip { // mul_fixed::base_field_element::Config: // - [advices[6], advices[7], advices[8]]: canon_advices // - // mul::incomplete::Config - // - advices[4]: lambda1 - // - advices[9]: z - // // TODO: Refactor away from `impl From for _` so that sub-configs can // equality-enable the columns they need to. for column in &advices { @@ -249,17 +235,8 @@ impl EccChip { advices[6], advices[7], advices[8], ); - // Components of mul::Config - // TODO: Move this into mul::Config. - let mul_hi = mul::incomplete::Config::configure( - meta, advices[9], advices[3], advices[0], advices[1], advices[4], advices[5], - ); - let mul_lo = mul::incomplete::Config::configure( - meta, advices[6], advices[7], advices[0], advices[1], advices[8], advices[2], - ); - let mul_complete = mul::complete::Config::configure(meta, advices[9], add); - let mul_overflow = - mul::overflow::Config::configure(meta, range_check, advices[6..9].try_into().unwrap()); + // Create variable-base scalar mul gates + let mul = mul::Config::configure(meta, add, range_check, advices); let config = EccConfig { advices, @@ -267,11 +244,7 @@ impl EccChip { fixed_z: meta.fixed_column(), add_incomplete, add, - mul_hi, - mul_lo, - mul_complete, - mul_overflow, - q_mul_lsb: meta.selector(), + mul, q_mul_fixed_full: meta.selector(), q_mul_fixed_short: meta.selector(), q_mul_fixed_base_field: meta.selector(), @@ -281,12 +254,6 @@ impl EccChip { running_sum_config, }; - // Create variable-base scalar mul gates - { - let mul_config: mul::Config = (&config).into(); - mul_config.create_gate(meta); - } - // Create gate that is used both in fixed-base mul using a short signed exponent, // and fixed-base mul using a base field element. { @@ -459,7 +426,7 @@ impl EccInstructions for EccChip { scalar: &Self::Var, base: &Self::NonIdentityPoint, ) -> Result<(Self::Point, Self::ScalarVar), Error> { - let config: mul::Config = self.config().into(); + let config = self.config().mul; config.assign( layouter.namespace(|| "variable-base scalar mul"), *scalar, diff --git a/src/circuit/gadget/ecc/chip/mul.rs b/src/circuit/gadget/ecc/chip/mul.rs index 173d7362..eebb1a02 100644 --- a/src/circuit/gadget/ecc/chip/mul.rs +++ b/src/circuit/gadget/ecc/chip/mul.rs @@ -1,27 +1,30 @@ -use super::{add, CellValue, EccConfig, EccPoint, NonIdentityEccPoint, Var}; +use super::{add, CellValue, EccPoint, NonIdentityEccPoint, Var}; use crate::{ - circuit::gadget::utilities::{bool_check, copy, ternary}, + circuit::gadget::utilities::{ + bool_check, copy, lookup_range_check::LookupRangeCheckConfig, ternary, + }, constants::T_Q, + primitives::sinsemilla, +}; +use std::{ + convert::TryInto, + ops::{Deref, Range}, }; -use std::ops::{Deref, Range}; use bigint::U256; use ff::PrimeField; use halo2::{ arithmetic::FieldExt, circuit::{Layouter, Region}, - plonk::{ConstraintSystem, Error, Selector}, + plonk::{Advice, Column, ConstraintSystem, Error, Selector}, poly::Rotation, }; use pasta_curves::pallas; -// TODO: Undo this pub(crate). -pub(crate) mod complete; -// TODO: Undo this pub(crate). -pub(crate) mod incomplete; -// TODO: Undo this pub(crate). -pub(crate) mod overflow; +mod complete; +mod incomplete; +mod overflow; /// Number of bits for which complete addition needs to be used in variable-base /// scalar multiplication @@ -36,17 +39,18 @@ const INCOMPLETE_RANGE: Range = 0..INCOMPLETE_LEN; // (It is a coincidence that k_{130} matches the boundary of the // overflow check described in [the book](https://zcash.github.io/halo2/design/gadgets/ecc/var-base-scalar-mul.html#overflow-check).) const INCOMPLETE_HI_RANGE: Range = 0..(INCOMPLETE_LEN / 2); -pub const INCOMPLETE_HI_LEN: usize = INCOMPLETE_LEN / 2; +const INCOMPLETE_HI_LEN: usize = INCOMPLETE_LEN / 2; // Bits k_{254} to k_{4} inclusive are used in incomplete addition. // The `lo` half is k_{129} to k_{4} inclusive (length 126 bits). const INCOMPLETE_LO_RANGE: Range = (INCOMPLETE_LEN / 2)..INCOMPLETE_LEN; -pub const INCOMPLETE_LO_LEN: usize = (INCOMPLETE_LEN / 2) + 1; +const INCOMPLETE_LO_LEN: usize = (INCOMPLETE_LEN / 2) + 1; // Bits k_{3} to k_{1} inclusive are used in complete addition. // Bit k_{0} is handled separately. const COMPLETE_RANGE: Range = INCOMPLETE_LEN..(INCOMPLETE_LEN + NUM_COMPLETE_BITS); +#[derive(Copy, Clone, Debug, Eq, PartialEq)] pub struct Config { // Selector used to check switching logic on LSB q_mul_lsb: Selector, @@ -62,17 +66,34 @@ pub struct Config { overflow_config: overflow::Config, } -impl From<&EccConfig> for Config { - fn from(ecc_config: &EccConfig) -> Self { +impl Config { + pub(super) fn configure( + meta: &mut ConstraintSystem, + add_config: add::Config, + lookup_config: LookupRangeCheckConfig, + advices: [Column; 10], + ) -> Self { + let hi_config = incomplete::Config::configure( + meta, advices[9], advices[3], advices[0], advices[1], advices[4], advices[5], + ); + let lo_config = incomplete::Config::configure( + meta, advices[6], advices[7], advices[0], advices[1], advices[8], advices[2], + ); + let complete_config = complete::Config::configure(meta, advices[9], add_config); + let overflow_config = + overflow::Config::configure(meta, lookup_config, advices[6..9].try_into().unwrap()); + let config = Self { - q_mul_lsb: ecc_config.q_mul_lsb, - add_config: ecc_config.add, - hi_config: ecc_config.mul_hi, - lo_config: ecc_config.mul_lo, - complete_config: ecc_config.mul_complete, - overflow_config: ecc_config.mul_overflow, + q_mul_lsb: meta.selector(), + add_config, + hi_config, + lo_config, + complete_config, + overflow_config, }; + config.create_gate(meta); + assert_eq!( config.hi_config.x_p, config.lo_config.x_p, "x_p is shared across hi and lo halves." @@ -109,10 +130,8 @@ impl From<&EccConfig> for Config { config } -} -impl Config { - pub(super) fn create_gate(&self, meta: &mut ConstraintSystem) { + fn create_gate(&self, meta: &mut ConstraintSystem) { // If `lsb` is 0, (x, y) = (x_p, -y_p). If `lsb` is 1, (x, y) = (0,0). meta.create_gate("LSB check", |meta| { let q_mul_lsb = meta.query_selector(self.q_mul_lsb); diff --git a/src/circuit/gadget/ecc/chip/mul/complete.rs b/src/circuit/gadget/ecc/chip/mul/complete.rs index 5c5ce049..20767f51 100644 --- a/src/circuit/gadget/ecc/chip/mul/complete.rs +++ b/src/circuit/gadget/ecc/chip/mul/complete.rs @@ -21,8 +21,7 @@ pub struct Config { } impl Config { - /// TODO: Make this pub(super). - pub(crate) fn configure( + pub(super) fn configure( meta: &mut ConstraintSystem, z_complete: Column, add_config: add::Config, diff --git a/src/circuit/gadget/ecc/chip/mul/incomplete.rs b/src/circuit/gadget/ecc/chip/mul/incomplete.rs index 63e6919d..3a980bd7 100644 --- a/src/circuit/gadget/ecc/chip/mul/incomplete.rs +++ b/src/circuit/gadget/ecc/chip/mul/incomplete.rs @@ -29,8 +29,7 @@ pub(crate) struct Config { } impl Config { - // TODO: Make this pub(super). - pub(crate) fn configure( + pub(super) fn configure( meta: &mut ConstraintSystem, z: Column, x_a: Column, diff --git a/src/circuit/gadget/ecc/chip/mul/overflow.rs b/src/circuit/gadget/ecc/chip/mul/overflow.rs index 4c21975b..57a94a41 100644 --- a/src/circuit/gadget/ecc/chip/mul/overflow.rs +++ b/src/circuit/gadget/ecc/chip/mul/overflow.rs @@ -26,8 +26,7 @@ pub struct Config { } impl Config { - // TODO: Make this pub(super). - pub(crate) fn configure( + pub(super) fn configure( meta: &mut ConstraintSystem, lookup_config: LookupRangeCheckConfig, advices: [Column; 3], From 1a7e832ed4ddf20eba225485afddcb2e89cc357a Mon Sep 17 00:00:00 2001 From: therealyingtong Date: Fri, 3 Dec 2021 11:51:59 -0500 Subject: [PATCH 29/59] chip::mul_fixed: Refactor mul_fixed::Config. This commit does not introduce circuit changes. --- src/circuit/gadget/ecc/chip.rs | 37 ++++++------ src/circuit/gadget/ecc/chip/mul_fixed.rs | 60 ++++++++++++------- .../ecc/chip/mul_fixed/base_field_elem.rs | 20 ++++--- .../gadget/ecc/chip/mul_fixed/full_width.rs | 6 +- .../gadget/ecc/chip/mul_fixed/short.rs | 6 +- 5 files changed, 72 insertions(+), 57 deletions(-) diff --git a/src/circuit/gadget/ecc/chip.rs b/src/circuit/gadget/ecc/chip.rs index f0d37992..6001261c 100644 --- a/src/circuit/gadget/ecc/chip.rs +++ b/src/circuit/gadget/ecc/chip.rs @@ -133,11 +133,6 @@ pub struct EccConfig { /// Advice columns needed by instructions in the ECC chip. pub advices: [Column; 10], - /// Coefficients of interpolation polynomials for x-coordinates (used in fixed-base scalar multiplication) - pub lagrange_coeffs: [Column; constants::H], - /// Fixed z such that y + z = u^2 some square, and -y + z is a non-square. (Used in fixed-base scalar multiplication) - pub fixed_z: Column, - /// Incomplete addition add_incomplete: add_incomplete::Config, @@ -147,6 +142,9 @@ pub struct EccConfig { /// Variable-base scalar multiplication mul: mul::Config, + /// TODO: Remove this. + pub mul_fixed: mul_fixed::Config, + /// Fixed-base full-width scalar multiplication pub q_mul_fixed_full: Selector, /// Fixed-base signed short scalar multiplication @@ -206,10 +204,6 @@ impl EccChip { ) -> >::Config { // The following columns need to be equality-enabled for their use in sub-configs: // - // mul_fixed::Config: - // - advices[4]: window - // - advices[5]: u - // // mul_fixed::base_field_element::Config: // - [advices[6], advices[7], advices[8]]: canon_advices // @@ -238,13 +232,26 @@ impl EccChip { // Create variable-base scalar mul gates let mul = mul::Config::configure(meta, add, range_check, advices); + // Create config that is shared across short, base-field, and full-width + // fixed-base scalar mul. + let mul_fixed = mul_fixed::Config::configure( + meta, + q_mul_fixed_running_sum, + lagrange_coeffs, + advices[4], + advices[0], + advices[1], + advices[5], + add, + add_incomplete, + ); + let config = EccConfig { advices, - lagrange_coeffs, - fixed_z: meta.fixed_column(), add_incomplete, add, mul, + mul_fixed, q_mul_fixed_full: meta.selector(), q_mul_fixed_short: meta.selector(), q_mul_fixed_base_field: meta.selector(), @@ -254,14 +261,6 @@ impl EccChip { running_sum_config, }; - // Create gate that is used both in fixed-base mul using a short signed exponent, - // and fixed-base mul using a base field element. - { - // The const generic does not matter when creating gates. - let mul_fixed_config: mul_fixed::Config<{ constants::NUM_WINDOWS }> = (&config).into(); - mul_fixed_config.running_sum_coords_gate(meta); - } - // Create gate that is only used in full-width fixed-base scalar mul. { let mul_fixed_full_config: mul_fixed::full_width::Config = (&config).into(); diff --git a/src/circuit/gadget/ecc/chip/mul_fixed.rs b/src/circuit/gadget/ecc/chip/mul_fixed.rs index e4e7fb01..18ef981a 100644 --- a/src/circuit/gadget/ecc/chip/mul_fixed.rs +++ b/src/circuit/gadget/ecc/chip/mul_fixed.rs @@ -1,6 +1,6 @@ use super::{ - add, add_incomplete, CellValue, EccBaseFieldElemFixed, EccConfig, EccScalarFixed, - EccScalarFixedShort, NonIdentityEccPoint, Var, + add, add_incomplete, CellValue, EccBaseFieldElemFixed, EccScalarFixed, EccScalarFixedShort, + NonIdentityEccPoint, Var, }; use crate::constants::{ self, @@ -75,8 +75,8 @@ impl OrchardFixedBases { } } -#[derive(Clone, Debug)] -pub struct Config { +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub struct Config { q_mul_fixed_running_sum: Selector, // The fixed Lagrange interpolation coefficients for `x_p`. lagrange_coeffs: [Column; constants::H], @@ -97,18 +97,32 @@ pub struct Config { add_incomplete_config: add_incomplete::Config, } -impl From<&EccConfig> for Config { - fn from(ecc_config: &EccConfig) -> Self { +impl Config { + #[allow(clippy::too_many_arguments)] + pub(super) fn configure( + meta: &mut ConstraintSystem, + q_mul_fixed_running_sum: Selector, + lagrange_coeffs: [Column; constants::H], + window: Column, + x_p: Column, + y_p: Column, + u: Column, + add_config: add::Config, + add_incomplete_config: add_incomplete::Config, + ) -> Self { + meta.enable_equality(window.into()); + meta.enable_equality(u.into()); + let config = Self { - q_mul_fixed_running_sum: ecc_config.q_mul_fixed_running_sum, - lagrange_coeffs: ecc_config.lagrange_coeffs, - fixed_z: ecc_config.fixed_z, - x_p: ecc_config.advices[0], - y_p: ecc_config.advices[1], - window: ecc_config.advices[4], - u: ecc_config.advices[5], - add_config: ecc_config.add, - add_incomplete_config: ecc_config.add_incomplete, + q_mul_fixed_running_sum, + lagrange_coeffs, + fixed_z: meta.fixed_column(), + window, + x_p, + y_p, + u, + add_config, + add_incomplete_config, }; // Check relationships between this config and `add_config`. @@ -141,11 +155,11 @@ impl From<&EccConfig> for Config { ); } + config.running_sum_coords_gate(meta); + config } -} -impl Config { /// Check that each window in the running sum decomposition uses the correct y_p /// and interpolated x_p. /// @@ -155,7 +169,7 @@ impl Config { /// This gate is not used in the mul_fixed::full_width helper, since the full-width /// scalar is witnessed directly as three-bit windows instead of being decomposed /// via a running sum. - pub(crate) fn running_sum_coords_gate(&self, meta: &mut ConstraintSystem) { + fn running_sum_coords_gate(&self, meta: &mut ConstraintSystem) { meta.create_gate("Running sum coordinates check", |meta| { let q_mul_fixed_running_sum = meta.query_selector(self.q_mul_fixed_running_sum); @@ -213,7 +227,7 @@ impl Config { } #[allow(clippy::type_complexity)] - fn assign_region_inner( + fn assign_region_inner( &self, region: &mut Region<'_, pallas::Base>, offset: usize, @@ -222,7 +236,7 @@ impl Config { coords_check_toggle: Selector, ) -> Result<(NonIdentityEccPoint, NonIdentityEccPoint), Error> { // Assign fixed columns for given fixed base - self.assign_fixed_constants(region, offset, base, coords_check_toggle)?; + self.assign_fixed_constants::(region, offset, base, coords_check_toggle)?; // Initialize accumulator let acc = self.initialize_accumulator(region, offset, base, scalar)?; @@ -231,12 +245,12 @@ impl Config { let acc = self.add_incomplete(region, offset, acc, base, scalar)?; // Process most significant window using complete addition - let mul_b = self.process_msb(region, offset, base, scalar)?; + let mul_b = self.process_msb::(region, offset, base, scalar)?; Ok((acc, mul_b)) } - fn assign_fixed_constants( + fn assign_fixed_constants( &self, region: &mut Region<'_, pallas::Base>, offset: usize, @@ -411,7 +425,7 @@ impl Config { Ok(acc) } - fn process_msb( + fn process_msb( &self, region: &mut Region<'_, pallas::Base>, offset: usize, diff --git a/src/circuit/gadget/ecc/chip/mul_fixed/base_field_elem.rs b/src/circuit/gadget/ecc/chip/mul_fixed/base_field_elem.rs index 63895545..fc3a9f60 100644 --- a/src/circuit/gadget/ecc/chip/mul_fixed/base_field_elem.rs +++ b/src/circuit/gadget/ecc/chip/mul_fixed/base_field_elem.rs @@ -24,7 +24,7 @@ pub struct Config { canon_advices: [Column; 3], lookup_config: LookupRangeCheckConfig, running_sum_config: RunningSumConfig, - super_config: super::Config<{ constants::NUM_WINDOWS }>, + super_config: super::Config, } impl From<&EccConfig> for Config { @@ -35,7 +35,7 @@ impl From<&EccConfig> for Config { canon_advices: [config.advices[6], config.advices[7], config.advices[8]], lookup_config: config.lookup_config, running_sum_config: config.running_sum_config.clone(), - super_config: config.into(), + super_config: config.mul_fixed, }; let add_incomplete_advices = config.super_config.add_incomplete_config.advice_columns(); @@ -180,13 +180,15 @@ impl Config { } }; - let (acc, mul_b) = self.super_config.assign_region_inner( - &mut region, - offset, - &(&scalar).into(), - base.into(), - self.q_mul_fixed_running_sum, - )?; + let (acc, mul_b) = self + .super_config + .assign_region_inner::<{ constants::NUM_WINDOWS }>( + &mut region, + offset, + &(&scalar).into(), + base.into(), + self.q_mul_fixed_running_sum, + )?; Ok((scalar, acc, mul_b)) }, diff --git a/src/circuit/gadget/ecc/chip/mul_fixed/full_width.rs b/src/circuit/gadget/ecc/chip/mul_fixed/full_width.rs index c4877089..257826fe 100644 --- a/src/circuit/gadget/ecc/chip/mul_fixed/full_width.rs +++ b/src/circuit/gadget/ecc/chip/mul_fixed/full_width.rs @@ -14,14 +14,14 @@ use pasta_curves::{arithmetic::FieldExt, pallas}; pub struct Config { q_mul_fixed_full: Selector, - super_config: super::Config, + super_config: super::Config, } impl From<&EccConfig> for Config { fn from(config: &EccConfig) -> Self { Self { q_mul_fixed_full: config.q_mul_fixed_full, - super_config: config.into(), + super_config: config.mul_fixed, } } } @@ -124,7 +124,7 @@ impl Config { let scalar = self.witness(&mut region, offset, scalar)?; - let (acc, mul_b) = self.super_config.assign_region_inner( + let (acc, mul_b) = self.super_config.assign_region_inner::( &mut region, offset, &(&scalar).into(), diff --git a/src/circuit/gadget/ecc/chip/mul_fixed/short.rs b/src/circuit/gadget/ecc/chip/mul_fixed/short.rs index 9ff8d625..1aa1cddc 100644 --- a/src/circuit/gadget/ecc/chip/mul_fixed/short.rs +++ b/src/circuit/gadget/ecc/chip/mul_fixed/short.rs @@ -21,7 +21,7 @@ pub struct Config { q_mul_fixed_short: Selector, q_mul_fixed_running_sum: Selector, running_sum_config: RunningSumConfig, - super_config: super::Config, + super_config: super::Config, } impl From<&EccConfig> for Config { @@ -30,7 +30,7 @@ impl From<&EccConfig> for Config { q_mul_fixed_short: config.q_mul_fixed_short, q_mul_fixed_running_sum: config.q_mul_fixed_running_sum, running_sum_config: config.running_sum_config.clone(), - super_config: config.into(), + super_config: config.mul_fixed, } } } @@ -110,7 +110,7 @@ impl Config { // Decompose the scalar let scalar = self.decompose(&mut region, offset, magnitude_sign)?; - let (acc, mul_b) = self.super_config.assign_region_inner( + let (acc, mul_b) = self.super_config.assign_region_inner::( &mut region, offset, &(&scalar).into(), From f472a16b325071fe1c00ca7727b58ba3a272629b Mon Sep 17 00:00:00 2001 From: therealyingtong Date: Tue, 30 Nov 2021 22:00:07 -0500 Subject: [PATCH 30/59] chip::mul_fixed: Move running_sum_config into mul_fixed::Config. --- src/circuit/gadget/ecc/chip.rs | 15 +- src/circuit/gadget/ecc/chip/mul_fixed.rs | 12 +- .../ecc/chip/mul_fixed/base_field_elem.rs | 14 +- .../gadget/ecc/chip/mul_fixed/full_width.rs | 16 +- .../gadget/ecc/chip/mul_fixed/short.rs | 14 +- .../gadget/utilities/decompose_running_sum.rs | 4 +- src/circuit_description | 2042 ++++++++--------- 7 files changed, 1049 insertions(+), 1068 deletions(-) diff --git a/src/circuit/gadget/ecc/chip.rs b/src/circuit/gadget/ecc/chip.rs index 6001261c..fd3d31d6 100644 --- a/src/circuit/gadget/ecc/chip.rs +++ b/src/circuit/gadget/ecc/chip.rs @@ -1,8 +1,7 @@ use super::EccInstructions; use crate::{ circuit::gadget::utilities::{ - copy, decompose_running_sum::RunningSumConfig, lookup_range_check::LookupRangeCheckConfig, - CellValue, UtilitiesInstructions, Var, + copy, lookup_range_check::LookupRangeCheckConfig, CellValue, UtilitiesInstructions, Var, }, constants::{self, NullifierK, OrchardFixedBasesFull, ValueCommitV}, primitives::sinsemilla, @@ -151,17 +150,12 @@ pub struct EccConfig { pub q_mul_fixed_short: Selector, /// Canonicity checks on base field element used as scalar in fixed-base mul pub q_mul_fixed_base_field: Selector, - /// Running sum decomposition of a scalar used in fixed-base mul. This is used - /// when the scalar is a signed short exponent or a base-field element. - pub q_mul_fixed_running_sum: Selector, /// Witness point witness_point: witness_point::Config, /// Lookup range check using 10-bit lookup table pub lookup_config: LookupRangeCheckConfig, - /// Running sum decomposition. - pub running_sum_config: RunningSumConfig, } /// A chip implementing EccInstructions @@ -213,10 +207,6 @@ impl EccChip { meta.enable_equality((*column).into()); } - let q_mul_fixed_running_sum = meta.selector(); - let running_sum_config = - RunningSumConfig::configure(meta, q_mul_fixed_running_sum, advices[4]); - // Create witness point gate let witness_point = witness_point::Config::configure(meta, advices[0], advices[1]); // Create incomplete point addition gate @@ -236,7 +226,6 @@ impl EccChip { // fixed-base scalar mul. let mul_fixed = mul_fixed::Config::configure( meta, - q_mul_fixed_running_sum, lagrange_coeffs, advices[4], advices[0], @@ -255,10 +244,8 @@ impl EccChip { q_mul_fixed_full: meta.selector(), q_mul_fixed_short: meta.selector(), q_mul_fixed_base_field: meta.selector(), - q_mul_fixed_running_sum, witness_point, lookup_config: range_check, - running_sum_config, }; // Create gate that is only used in full-width fixed-base scalar mul. diff --git a/src/circuit/gadget/ecc/chip/mul_fixed.rs b/src/circuit/gadget/ecc/chip/mul_fixed.rs index 18ef981a..38afca53 100644 --- a/src/circuit/gadget/ecc/chip/mul_fixed.rs +++ b/src/circuit/gadget/ecc/chip/mul_fixed.rs @@ -2,6 +2,7 @@ use super::{ add, add_incomplete, CellValue, EccBaseFieldElemFixed, EccScalarFixed, EccScalarFixedShort, NonIdentityEccPoint, Var, }; +use crate::circuit::gadget::utilities::decompose_running_sum::RunningSumConfig; use crate::constants::{ self, load::{NullifierK, OrchardFixedBase, OrchardFixedBasesFull, ValueCommitV, WindowUs}, @@ -77,7 +78,7 @@ impl OrchardFixedBases { #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct Config { - q_mul_fixed_running_sum: Selector, + running_sum_config: RunningSumConfig, // The fixed Lagrange interpolation coefficients for `x_p`. lagrange_coeffs: [Column; constants::H], // The fixed `z` for each window such that `y + z = u^2`. @@ -101,7 +102,6 @@ impl Config { #[allow(clippy::too_many_arguments)] pub(super) fn configure( meta: &mut ConstraintSystem, - q_mul_fixed_running_sum: Selector, lagrange_coeffs: [Column; constants::H], window: Column, x_p: Column, @@ -113,8 +113,11 @@ impl Config { meta.enable_equality(window.into()); meta.enable_equality(u.into()); + let q_running_sum = meta.selector(); + let running_sum_config = RunningSumConfig::configure(meta, q_running_sum, window); + let config = Self { - q_mul_fixed_running_sum, + running_sum_config, lagrange_coeffs, fixed_z: meta.fixed_column(), window, @@ -171,7 +174,8 @@ impl Config { /// via a running sum. fn running_sum_coords_gate(&self, meta: &mut ConstraintSystem) { meta.create_gate("Running sum coordinates check", |meta| { - let q_mul_fixed_running_sum = meta.query_selector(self.q_mul_fixed_running_sum); + let q_mul_fixed_running_sum = + meta.query_selector(self.running_sum_config.q_range_check); let z_cur = meta.query_advice(self.window, Rotation::cur()); let z_next = meta.query_advice(self.window, Rotation::next()); diff --git a/src/circuit/gadget/ecc/chip/mul_fixed/base_field_elem.rs b/src/circuit/gadget/ecc/chip/mul_fixed/base_field_elem.rs index fc3a9f60..e1c7169c 100644 --- a/src/circuit/gadget/ecc/chip/mul_fixed/base_field_elem.rs +++ b/src/circuit/gadget/ecc/chip/mul_fixed/base_field_elem.rs @@ -3,8 +3,8 @@ use super::H_BASE; use crate::{ circuit::gadget::utilities::{ - bitrange_subset, copy, decompose_running_sum::RunningSumConfig, - lookup_range_check::LookupRangeCheckConfig, range_check, CellValue, Var, + bitrange_subset, copy, lookup_range_check::LookupRangeCheckConfig, range_check, CellValue, + Var, }, constants::{self, T_P}, primitives::sinsemilla, @@ -19,22 +19,18 @@ use pasta_curves::{arithmetic::FieldExt, pallas}; use std::convert::TryInto; pub struct Config { - q_mul_fixed_running_sum: Selector, q_mul_fixed_base_field: Selector, canon_advices: [Column; 3], lookup_config: LookupRangeCheckConfig, - running_sum_config: RunningSumConfig, super_config: super::Config, } impl From<&EccConfig> for Config { fn from(config: &EccConfig) -> Self { let config = Self { - q_mul_fixed_running_sum: config.q_mul_fixed_running_sum, q_mul_fixed_base_field: config.q_mul_fixed_base_field, canon_advices: [config.advices[6], config.advices[7], config.advices[8]], lookup_config: config.lookup_config, - running_sum_config: config.running_sum_config.clone(), super_config: config.mul_fixed, }; @@ -46,8 +42,6 @@ impl From<&EccConfig> for Config { ); } - assert_eq!(config.running_sum_config.z, config.super_config.window); - config } } @@ -166,7 +160,7 @@ impl Config { // Decompose scalar let scalar = { - let running_sum = self.running_sum_config.copy_decompose( + let running_sum = self.super_config.running_sum_config.copy_decompose( &mut region, offset, scalar, @@ -187,7 +181,7 @@ impl Config { offset, &(&scalar).into(), base.into(), - self.q_mul_fixed_running_sum, + self.super_config.running_sum_config.q_range_check, )?; Ok((scalar, acc, mul_b)) diff --git a/src/circuit/gadget/ecc/chip/mul_fixed/full_width.rs b/src/circuit/gadget/ecc/chip/mul_fixed/full_width.rs index 257826fe..a5863587 100644 --- a/src/circuit/gadget/ecc/chip/mul_fixed/full_width.rs +++ b/src/circuit/gadget/ecc/chip/mul_fixed/full_width.rs @@ -124,13 +124,15 @@ impl Config { let scalar = self.witness(&mut region, offset, scalar)?; - let (acc, mul_b) = self.super_config.assign_region_inner::( - &mut region, - offset, - &(&scalar).into(), - base.into(), - self.q_mul_fixed_full, - )?; + let (acc, mul_b) = self + .super_config + .assign_region_inner::<{ constants::NUM_WINDOWS }>( + &mut region, + offset, + &(&scalar).into(), + base.into(), + self.q_mul_fixed_full, + )?; Ok((scalar, acc, mul_b)) }, diff --git a/src/circuit/gadget/ecc/chip/mul_fixed/short.rs b/src/circuit/gadget/ecc/chip/mul_fixed/short.rs index 1aa1cddc..50f3550f 100644 --- a/src/circuit/gadget/ecc/chip/mul_fixed/short.rs +++ b/src/circuit/gadget/ecc/chip/mul_fixed/short.rs @@ -2,10 +2,8 @@ use std::{array, convert::TryInto}; use super::super::{EccConfig, EccPoint, EccScalarFixedShort}; use crate::{ - circuit::gadget::utilities::{ - bool_check, copy, decompose_running_sum::RunningSumConfig, CellValue, Var, - }, - constants::{ValueCommitV, FIXED_BASE_WINDOW_SIZE, L_VALUE, NUM_WINDOWS_SHORT}, + circuit::gadget::utilities::{bool_check, copy, CellValue, Var}, + constants::{ValueCommitV, L_VALUE, NUM_WINDOWS_SHORT}, }; use halo2::{ @@ -19,8 +17,6 @@ use pasta_curves::pallas; pub struct Config { // Selector used for fixed-base scalar mul with short signed exponent. q_mul_fixed_short: Selector, - q_mul_fixed_running_sum: Selector, - running_sum_config: RunningSumConfig, super_config: super::Config, } @@ -28,8 +24,6 @@ impl From<&EccConfig> for Config { fn from(config: &EccConfig) -> Self { Self { q_mul_fixed_short: config.q_mul_fixed_short, - q_mul_fixed_running_sum: config.q_mul_fixed_running_sum, - running_sum_config: config.running_sum_config.clone(), super_config: config.mul_fixed, } } @@ -80,7 +74,7 @@ impl Config { let (magnitude, sign) = magnitude_sign; // Decompose magnitude - let running_sum = self.running_sum_config.copy_decompose( + let running_sum = self.super_config.running_sum_config.copy_decompose( region, offset, magnitude, @@ -115,7 +109,7 @@ impl Config { offset, &(&scalar).into(), base.clone().into(), - self.q_mul_fixed_running_sum, + self.super_config.running_sum_config.q_range_check, )?; Ok((scalar, acc, mul_b)) diff --git a/src/circuit/gadget/utilities/decompose_running_sum.rs b/src/circuit/gadget/utilities/decompose_running_sum.rs index c59de1c7..c5f6823e 100644 --- a/src/circuit/gadget/utilities/decompose_running_sum.rs +++ b/src/circuit/gadget/utilities/decompose_running_sum.rs @@ -44,9 +44,9 @@ impl std::ops::Deref for RunningSum { } } -#[derive(Debug, Clone, Eq, PartialEq)] +#[derive(Debug, Clone, Copy, Eq, PartialEq)] pub struct RunningSumConfig { - q_range_check: Selector, + pub q_range_check: Selector, pub z: Column, _marker: PhantomData, } diff --git a/src/circuit_description b/src/circuit_description index 46141a26..9ff4e74f 100644 --- a/src/circuit_description +++ b/src/circuit_description @@ -37,19 +37,15 @@ PinnedVerificationKey { column_type: Fixed, }, Column { - index: 20, + index: 19, column_type: Fixed, }, Column { - index: 20, + index: 19, column_type: Fixed, }, Column { - index: 20, - column_type: Fixed, - }, - Column { - index: 20, + index: 19, column_type: Fixed, }, Column { @@ -65,19 +61,23 @@ PinnedVerificationKey { column_type: Fixed, }, Column { - index: 21, + index: 20, column_type: Fixed, }, Column { - index: 21, + index: 20, column_type: Fixed, }, Column { - index: 21, + index: 20, column_type: Fixed, }, Column { - index: 21, + index: 20, + column_type: Fixed, + }, + Column { + index: 20, column_type: Fixed, }, Column { @@ -93,15 +93,15 @@ PinnedVerificationKey { column_type: Fixed, }, Column { - index: 22, + index: 21, column_type: Fixed, }, Column { - index: 22, + index: 21, column_type: Fixed, }, Column { - index: 22, + index: 21, column_type: Fixed, }, Column { @@ -940,254 +940,14 @@ PinnedVerificationKey { ), ), ), - Product( - Fixed { - query_index: 19, - column_index: 19, - rotation: Rotation( - 0, - ), - }, - Product( - Product( - Product( - Product( - Product( - Product( - Product( - Sum( - Advice { - query_index: 4, - column_index: 4, - rotation: Rotation( - 0, - ), - }, - Negated( - Scaled( - Advice { - query_index: 12, - column_index: 4, - rotation: Rotation( - 1, - ), - }, - 0x0000000000000000000000000000000000000000000000000000000000000008, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Sum( - Advice { - query_index: 4, - column_index: 4, - rotation: Rotation( - 0, - ), - }, - Negated( - Scaled( - Advice { - query_index: 12, - column_index: 4, - rotation: Rotation( - 1, - ), - }, - 0x0000000000000000000000000000000000000000000000000000000000000008, - ), - ), - ), - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Sum( - Advice { - query_index: 4, - column_index: 4, - rotation: Rotation( - 0, - ), - }, - Negated( - Scaled( - Advice { - query_index: 12, - column_index: 4, - rotation: Rotation( - 1, - ), - }, - 0x0000000000000000000000000000000000000000000000000000000000000008, - ), - ), - ), - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, - ), - Negated( - Sum( - Advice { - query_index: 4, - column_index: 4, - rotation: Rotation( - 0, - ), - }, - Negated( - Scaled( - Advice { - query_index: 12, - column_index: 4, - rotation: Rotation( - 1, - ), - }, - 0x0000000000000000000000000000000000000000000000000000000000000008, - ), - ), - ), - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, - ), - Negated( - Sum( - Advice { - query_index: 4, - column_index: 4, - rotation: Rotation( - 0, - ), - }, - Negated( - Scaled( - Advice { - query_index: 12, - column_index: 4, - rotation: Rotation( - 1, - ), - }, - 0x0000000000000000000000000000000000000000000000000000000000000008, - ), - ), - ), - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, - ), - Negated( - Sum( - Advice { - query_index: 4, - column_index: 4, - rotation: Rotation( - 0, - ), - }, - Negated( - Scaled( - Advice { - query_index: 12, - column_index: 4, - rotation: Rotation( - 1, - ), - }, - 0x0000000000000000000000000000000000000000000000000000000000000008, - ), - ), - ), - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, - ), - Negated( - Sum( - Advice { - query_index: 4, - column_index: 4, - rotation: Rotation( - 0, - ), - }, - Negated( - Scaled( - Advice { - query_index: 12, - column_index: 4, - rotation: Rotation( - 1, - ), - }, - 0x0000000000000000000000000000000000000000000000000000000000000008, - ), - ), - ), - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, - ), - Negated( - Sum( - Advice { - query_index: 4, - column_index: 4, - rotation: Rotation( - 0, - ), - }, - Negated( - Scaled( - Advice { - query_index: 12, - column_index: 4, - rotation: Rotation( - 1, - ), - }, - 0x0000000000000000000000000000000000000000000000000000000000000008, - ), - ), - ), - ), - ), - ), - ), Product( Product( Product( Product( Product( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -1198,8 +958,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -1213,8 +973,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -1228,8 +988,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -1304,8 +1064,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -1316,8 +1076,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -1331,8 +1091,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -1346,8 +1106,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -1421,8 +1181,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -1433,8 +1193,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -1448,8 +1208,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -1463,8 +1223,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -1530,8 +1290,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -1542,8 +1302,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -1557,8 +1317,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -1572,8 +1332,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -1587,7 +1347,7 @@ PinnedVerificationKey { Sum( Sum( Advice { - query_index: 13, + query_index: 12, column_index: 2, rotation: Rotation( 1, @@ -1694,8 +1454,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -1706,8 +1466,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -1721,8 +1481,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -1736,8 +1496,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -1749,7 +1509,7 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 14, + query_index: 13, column_index: 3, rotation: Rotation( 1, @@ -1812,7 +1572,7 @@ PinnedVerificationKey { }, Negated( Advice { - query_index: 13, + query_index: 12, column_index: 2, rotation: Rotation( 1, @@ -1829,8 +1589,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -1841,8 +1601,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -1856,8 +1616,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -1871,8 +1631,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -1955,8 +1715,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -1967,8 +1727,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -1982,8 +1742,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -1997,8 +1757,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -2094,8 +1854,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -2106,8 +1866,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -2121,8 +1881,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -2136,8 +1896,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -2223,7 +1983,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 13, + query_index: 12, column_index: 2, rotation: Rotation( 1, @@ -2238,8 +1998,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -2250,8 +2010,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -2265,8 +2025,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -2280,8 +2040,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -2346,7 +2106,7 @@ PinnedVerificationKey { }, Negated( Advice { - query_index: 13, + query_index: 12, column_index: 2, rotation: Rotation( 1, @@ -2367,7 +2127,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 14, + query_index: 13, column_index: 3, rotation: Rotation( 1, @@ -2382,8 +2142,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -2394,8 +2154,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -2409,8 +2169,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -2424,8 +2184,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -2509,7 +2269,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 13, + query_index: 12, column_index: 2, rotation: Rotation( 1, @@ -2524,8 +2284,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -2536,8 +2296,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -2551,8 +2311,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -2566,8 +2326,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -2630,7 +2390,7 @@ PinnedVerificationKey { }, Negated( Advice { - query_index: 13, + query_index: 12, column_index: 2, rotation: Rotation( 1, @@ -2651,7 +2411,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 14, + query_index: 13, column_index: 3, rotation: Rotation( 1, @@ -2666,8 +2426,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -2678,8 +2438,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -2693,8 +2453,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -2708,8 +2468,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -2743,7 +2503,7 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 13, + query_index: 12, column_index: 2, rotation: Rotation( 1, @@ -2766,8 +2526,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -2778,8 +2538,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -2793,8 +2553,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -2808,8 +2568,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -2843,7 +2603,7 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 14, + query_index: 13, column_index: 3, rotation: Rotation( 1, @@ -2866,8 +2626,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -2878,8 +2638,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -2893,8 +2653,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -2908,8 +2668,108 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 12, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -2944,106 +2804,6 @@ PinnedVerificationKey { Sum( Advice { query_index: 13, - column_index: 2, - rotation: Rotation( - 1, - ), - }, - Negated( - Advice { - query_index: 0, - column_index: 0, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - ), - Product( - Product( - Product( - Product( - Fixed { - query_index: 20, - column_index: 20, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 20, - column_index: 20, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 20, - column_index: 20, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, - ), - Negated( - Fixed { - query_index: 20, - column_index: 20, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Product( - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Product( - Advice { - query_index: 2, - column_index: 2, - rotation: Rotation( - 0, - ), - }, - Advice { - query_index: 7, - column_index: 7, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Advice { - query_index: 14, column_index: 3, rotation: Rotation( 1, @@ -3066,8 +2826,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -3078,8 +2838,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -3093,8 +2853,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -3108,8 +2868,137 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Sum( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Product( + Sum( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Advice { + query_index: 12, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -3183,135 +3072,6 @@ PinnedVerificationKey { ), Advice { query_index: 13, - column_index: 2, - rotation: Rotation( - 1, - ), - }, - ), - ), - Product( - Product( - Product( - Product( - Fixed { - query_index: 20, - column_index: 20, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 20, - column_index: 20, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 20, - column_index: 20, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, - ), - Negated( - Fixed { - query_index: 20, - column_index: 20, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Product( - Sum( - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Product( - Sum( - Advice { - query_index: 2, - column_index: 2, - rotation: Rotation( - 0, - ), - }, - Negated( - Advice { - query_index: 0, - column_index: 0, - rotation: Rotation( - 0, - ), - }, - ), - ), - Advice { - query_index: 5, - column_index: 5, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Negated( - Product( - Sum( - Advice { - query_index: 3, - column_index: 3, - rotation: Rotation( - 0, - ), - }, - Advice { - query_index: 1, - column_index: 1, - rotation: Rotation( - 0, - ), - }, - ), - Advice { - query_index: 8, - column_index: 8, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Advice { - query_index: 14, column_index: 3, rotation: Rotation( 1, @@ -3420,7 +3180,7 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 12, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -3436,7 +3196,7 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 14, + query_index: 13, column_index: 3, rotation: Rotation( 1, @@ -3447,14 +3207,14 @@ PinnedVerificationKey { Sum( Product( Advice { - query_index: 12, + query_index: 14, column_index: 4, rotation: Rotation( 1, ), }, Advice { - query_index: 12, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -3463,7 +3223,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 14, + query_index: 13, column_index: 3, rotation: Rotation( 1, @@ -4184,7 +3944,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 14, + query_index: 13, column_index: 3, rotation: Rotation( 1, @@ -4352,7 +4112,7 @@ PinnedVerificationKey { }, Negated( Advice { - query_index: 14, + query_index: 13, column_index: 3, rotation: Rotation( 1, @@ -4439,7 +4199,7 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 12, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -4455,7 +4215,7 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 14, + query_index: 13, column_index: 3, rotation: Rotation( 1, @@ -4466,14 +4226,14 @@ PinnedVerificationKey { Sum( Product( Advice { - query_index: 12, + query_index: 14, column_index: 4, rotation: Rotation( 1, ), }, Advice { - query_index: 12, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -4482,7 +4242,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 14, + query_index: 13, column_index: 3, rotation: Rotation( 1, @@ -4989,7 +4749,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 14, + query_index: 13, column_index: 3, rotation: Rotation( 1, @@ -5157,7 +4917,7 @@ PinnedVerificationKey { }, Negated( Advice { - query_index: 14, + query_index: 13, column_index: 3, rotation: Rotation( 1, @@ -5241,7 +5001,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 12, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -5256,8 +5016,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -5268,8 +5028,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -5283,8 +5043,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -5298,8 +5058,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -5313,8 +5073,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -5342,7 +5102,7 @@ PinnedVerificationKey { ), }, Advice { - query_index: 13, + query_index: 12, column_index: 2, rotation: Rotation( 1, @@ -5410,8 +5170,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -5422,8 +5182,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -5437,8 +5197,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -5452,8 +5212,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -5467,8 +5227,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -5501,8 +5261,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -5513,8 +5273,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -5528,8 +5288,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -5543,8 +5303,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -5558,8 +5318,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -5592,8 +5352,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -5604,8 +5364,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -5619,8 +5379,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -5634,8 +5394,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -5649,8 +5409,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -5716,8 +5476,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -5728,8 +5488,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -5743,8 +5503,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -5758,8 +5518,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -5773,8 +5533,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -5932,8 +5692,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -5944,8 +5704,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -5959,8 +5719,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -5974,8 +5734,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -5989,8 +5749,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -6085,8 +5845,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -6097,8 +5857,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -6112,8 +5872,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -6127,8 +5887,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -6142,8 +5902,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -6265,7 +6025,7 @@ PinnedVerificationKey { ), }, Advice { - query_index: 13, + query_index: 12, column_index: 2, rotation: Rotation( 1, @@ -6333,8 +6093,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -6345,8 +6105,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -6360,8 +6120,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -6375,8 +6135,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -6390,8 +6150,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -6457,8 +6217,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -6469,8 +6229,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -6484,8 +6244,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -6499,8 +6259,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -6514,8 +6274,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -6673,8 +6433,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -6685,8 +6445,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -6700,8 +6460,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -6715,8 +6475,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -6730,8 +6490,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -6826,8 +6586,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -6838,8 +6598,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -6853,8 +6613,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -6868,8 +6628,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -6883,8 +6643,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -7011,8 +6771,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -7023,8 +6783,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -7038,8 +6798,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -7053,8 +6813,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -7068,8 +6828,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -7139,8 +6899,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -7151,8 +6911,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -7166,8 +6926,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -7181,8 +6941,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -7196,8 +6956,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -7305,8 +7065,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -7317,8 +7077,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -7332,8 +7092,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -7347,8 +7107,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -7362,8 +7122,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -7415,8 +7175,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -7427,8 +7187,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -7442,8 +7202,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -7457,8 +7217,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -7472,8 +7232,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -7513,8 +7273,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -7525,8 +7285,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -7540,8 +7300,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -7555,8 +7315,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -7570,8 +7330,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -7609,8 +7369,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -7621,8 +7381,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -7636,8 +7396,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -7651,8 +7411,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -7666,8 +7426,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -7698,8 +7458,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -7710,8 +7470,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -7725,8 +7485,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -7740,8 +7500,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -7755,8 +7515,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -7818,8 +7578,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -7830,8 +7590,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -7845,8 +7605,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -7860,8 +7620,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -7926,8 +7686,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -7938,8 +7698,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -7953,8 +7713,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -7968,8 +7728,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -8063,8 +7823,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -8075,8 +7835,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -8090,8 +7850,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -8105,8 +7865,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -8195,8 +7955,248 @@ PinnedVerificationKey { ), Product( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + ), + ), + ), + Product( + Fixed { + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -8242,7 +8242,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 12, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -8279,7 +8279,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 12, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -8301,7 +8301,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 12, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -8339,7 +8339,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 12, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -8361,7 +8361,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 12, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -8383,7 +8383,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 12, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -8422,7 +8422,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 12, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -8444,7 +8444,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 12, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -8466,7 +8466,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 12, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -8488,7 +8488,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 12, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -8528,7 +8528,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 12, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -8550,7 +8550,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 12, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -8572,7 +8572,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 12, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -8594,7 +8594,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 12, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -8616,7 +8616,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 12, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -8657,7 +8657,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 12, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -8679,7 +8679,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 12, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -8701,7 +8701,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 12, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -8723,7 +8723,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 12, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -8745,7 +8745,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 12, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -8767,7 +8767,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 12, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -8809,7 +8809,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 12, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -8831,7 +8831,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 12, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -8853,7 +8853,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 12, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -8875,7 +8875,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 12, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -8897,7 +8897,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 12, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -8919,7 +8919,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 12, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -8941,7 +8941,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 12, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -8974,8 +8974,8 @@ PinnedVerificationKey { ), Product( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -9021,8 +9021,8 @@ PinnedVerificationKey { ), Product( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -9708,8 +9708,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -9720,8 +9720,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -9735,8 +9735,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -9750,8 +9750,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -9788,8 +9788,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -9800,8 +9800,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -9815,8 +9815,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -9830,8 +9830,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -9868,8 +9868,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -9880,8 +9880,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -9895,8 +9895,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -9910,8 +9910,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -9961,8 +9961,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -9973,8 +9973,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -9988,8 +9988,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -10003,8 +10003,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -10045,8 +10045,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -10057,8 +10057,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -10072,8 +10072,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -10087,8 +10087,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -10118,8 +10118,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -10130,8 +10130,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -10145,8 +10145,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -10160,8 +10160,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -10207,8 +10207,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -10219,8 +10219,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -10234,8 +10234,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -10249,8 +10249,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -10324,8 +10324,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -10336,8 +10336,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -10351,8 +10351,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -10366,8 +10366,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -10397,8 +10397,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -10409,8 +10409,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -10424,8 +10424,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -10439,8 +10439,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -10509,8 +10509,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -10521,8 +10521,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -10536,8 +10536,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -10551,8 +10551,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -10589,8 +10589,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -10601,8 +10601,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -10616,8 +10616,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -10631,8 +10631,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -10676,8 +10676,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -10688,8 +10688,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -10703,8 +10703,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -10718,8 +10718,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -10777,8 +10777,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -10789,8 +10789,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -10804,8 +10804,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -10819,8 +10819,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -11122,8 +11122,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -11134,8 +11134,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -11149,8 +11149,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -11164,8 +11164,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -11467,8 +11467,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -11479,8 +11479,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -11494,8 +11494,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -11509,8 +11509,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 22, - column_index: 22, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -13295,14 +13295,14 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 14, + query_index: 13, column_index: 3, rotation: Rotation( 1, ), }, Advice { - query_index: 12, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -13322,14 +13322,14 @@ PinnedVerificationKey { Sum( Product( Advice { - query_index: 14, + query_index: 13, column_index: 3, rotation: Rotation( 1, ), }, Advice { - query_index: 14, + query_index: 13, column_index: 3, rotation: Rotation( 1, @@ -13389,7 +13389,7 @@ PinnedVerificationKey { 0x0000000000000000000000000000000000000000000000000000000000000002, ), Advice { - query_index: 14, + query_index: 13, column_index: 3, rotation: Rotation( 1, @@ -13810,7 +13810,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 12, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -13941,7 +13941,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 13, + query_index: 12, column_index: 2, rotation: Rotation( 1, @@ -14055,7 +14055,7 @@ PinnedVerificationKey { Sum( Sum( Advice { - query_index: 14, + query_index: 13, column_index: 3, rotation: Rotation( 1, @@ -14182,7 +14182,7 @@ PinnedVerificationKey { Negated( Sum( Advice { - query_index: 13, + query_index: 12, column_index: 2, rotation: Rotation( 1, @@ -14190,7 +14190,7 @@ PinnedVerificationKey { }, Scaled( Advice { - query_index: 14, + query_index: 13, column_index: 3, rotation: Rotation( 1, @@ -15920,7 +15920,7 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 12, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -15932,7 +15932,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 12, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -16163,7 +16163,7 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 13, + query_index: 12, column_index: 2, rotation: Rotation( 1, @@ -16172,7 +16172,7 @@ PinnedVerificationKey { Negated( Sum( Advice { - query_index: 14, + query_index: 13, column_index: 3, rotation: Rotation( 1, @@ -16180,7 +16180,7 @@ PinnedVerificationKey { }, Scaled( Advice { - query_index: 12, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -16435,7 +16435,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 14, + query_index: 13, column_index: 3, rotation: Rotation( 1, @@ -16446,7 +16446,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 12, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -16990,14 +16990,14 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 12, + query_index: 14, column_index: 4, rotation: Rotation( 1, ), }, Advice { - query_index: 14, + query_index: 13, column_index: 3, rotation: Rotation( 1, @@ -17095,7 +17095,7 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 12, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -17331,7 +17331,7 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 12, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -27256,15 +27256,6 @@ PinnedVerificationKey { -1, ), ), - ( - Column { - index: 4, - column_type: Advice, - }, - Rotation( - 1, - ), - ), ( Column { index: 2, @@ -27283,6 +27274,15 @@ PinnedVerificationKey { 1, ), ), + ( + Column { + index: 4, + column_type: Advice, + }, + Rotation( + 1, + ), + ), ( Column { index: 5, @@ -27846,7 +27846,7 @@ PinnedVerificationKey { ), ), Advice { - query_index: 13, + query_index: 12, column_index: 2, rotation: Rotation( 1, @@ -28333,10 +28333,10 @@ PinnedVerificationKey { (0x1f777f0e4263ec4a19f30813739c640335ffa951cc3cc586b6c4095e737f95be, 0x061c07fb12cb19582eefd858a08e689acd970c8cb9ed8f7b928d88e691a2f586), (0x13d0bd76da4ace22c0e90b098d6073551322b8c734bf37eeca67fbf19687f550, 0x3d996cc9da5a31cefb453390b906eabbcc75797bc6a6b9c9e3af2fe7b6b8beed), (0x04cad7405b492a30db0a710c842cecc97d02059acf4c02aa79626dce68ac4837, 0x3d6d7b6698b258e61ebe0b25d9cbcd4a016cb0a2ae8d92752532d98cfb27720d), - (0x0974ad1a3c0eb4c8d2c59cd820a82b7f28ea2f7a245008d403815131ff30879e, 0x00bb593cdf920cef4965f788d65eba3c3aa07d9718dfb62e3e385849a0d692a8), (0x1b6f5383c5a0ae5bf457e1c8e17a933e892464d33fef9e9262411e01c117d87e, 0x0c552b960e8ce365b5f2302bcc0b7ce5cdf964e6036602cfc859c8769184f619), (0x3fa4b5cc33e30de3ac7342c84f47f4fffe7ae77dda1689c2f08050d0ab743cb1, 0x327663e39b128ec28c94486b1e5d4429000626f65230ed572c66f80406a42176), (0x2184a7d65b5000cc5c5f178c2f4ab5b11a67fdc626771c29ade508020c8da032, 0x34c98ee1f6dfa6c1e8cd915d1efeb484206e13e5e32e13118925913568e620b7), + (0x0974ad1a3c0eb4c8d2c59cd820a82b7f28ea2f7a245008d403815131ff30879e, 0x00bb593cdf920cef4965f788d65eba3c3aa07d9718dfb62e3e385849a0d692a8), (0x1e355d783cffccafc120f462461fb312773442762383ac444009653f3d8d4be6, 0x3c60e17b18492aa2c41798b409d2bcc1857ca57ee9d2fb0001584cedc8e141d6), (0x0a6fe1cc1ce659681079768ca8ff94d82c7d51ef39cd99b738b144de3a3027f6, 0x30cfc2f4e0ec95f623199970d8b762647ad2d7c3591a20781ee8187702babe5f), (0x00d87a2c430f1db50a63f18f8cf8807f4f70d3acb940d4130ba6811f8ba2d479, 0x13d5742320e1b2cecda6073b7f2bf5816b9067453deeaa829f356a65ef5621b2), From 165c9b6941dd7ff732bee28c45c2b64bed1d451d Mon Sep 17 00:00:00 2001 From: therealyingtong Date: Tue, 30 Nov 2021 22:15:19 -0500 Subject: [PATCH 31/59] mul_fixed::full_width: Refactor full_width::Config. This commit does not result in circuit changes. --- src/circuit/gadget/ecc/chip.rs | 15 ++++------ .../gadget/ecc/chip/mul_fixed/full_width.rs | 28 +++++++++++-------- 2 files changed, 23 insertions(+), 20 deletions(-) diff --git a/src/circuit/gadget/ecc/chip.rs b/src/circuit/gadget/ecc/chip.rs index fd3d31d6..230625bc 100644 --- a/src/circuit/gadget/ecc/chip.rs +++ b/src/circuit/gadget/ecc/chip.rs @@ -145,7 +145,7 @@ pub struct EccConfig { pub mul_fixed: mul_fixed::Config, /// Fixed-base full-width scalar multiplication - pub q_mul_fixed_full: Selector, + mul_fixed_full: mul_fixed::full_width::Config, /// Fixed-base signed short scalar multiplication pub q_mul_fixed_short: Selector, /// Canonicity checks on base field element used as scalar in fixed-base mul @@ -235,25 +235,22 @@ impl EccChip { add_incomplete, ); + // Create gate that is only used in full-width fixed-base scalar mul. + let mul_fixed_full = mul_fixed::full_width::Config::configure(meta, mul_fixed); + let config = EccConfig { advices, add_incomplete, add, mul, mul_fixed, - q_mul_fixed_full: meta.selector(), + mul_fixed_full, q_mul_fixed_short: meta.selector(), q_mul_fixed_base_field: meta.selector(), witness_point, lookup_config: range_check, }; - // Create gate that is only used in full-width fixed-base scalar mul. - { - let mul_fixed_full_config: mul_fixed::full_width::Config = (&config).into(); - mul_fixed_full_config.create_gate(meta); - } - // Create gate that is only used in short fixed-base scalar mul. { let short_config: mul_fixed::short::Config = (&config).into(); @@ -426,7 +423,7 @@ impl EccInstructions for EccChip { scalar: Option, base: &Self::FixedPoints, ) -> Result<(Self::Point, Self::ScalarFixed), Error> { - let config: mul_fixed::full_width::Config = self.config().into(); + let config = self.config().mul_fixed_full; config.assign( layouter.namespace(|| format!("fixed-base mul of {:?}", base)), scalar, diff --git a/src/circuit/gadget/ecc/chip/mul_fixed/full_width.rs b/src/circuit/gadget/ecc/chip/mul_fixed/full_width.rs index a5863587..6db138b0 100644 --- a/src/circuit/gadget/ecc/chip/mul_fixed/full_width.rs +++ b/src/circuit/gadget/ecc/chip/mul_fixed/full_width.rs @@ -1,4 +1,4 @@ -use super::super::{EccConfig, EccPoint, EccScalarFixed, OrchardFixedBasesFull}; +use super::super::{EccPoint, EccScalarFixed, OrchardFixedBasesFull}; use crate::{ circuit::gadget::utilities::{range_check, CellValue, Var}, @@ -12,22 +12,28 @@ use halo2::{ }; use pasta_curves::{arithmetic::FieldExt, pallas}; +#[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct Config { q_mul_fixed_full: Selector, super_config: super::Config, } -impl From<&EccConfig> for Config { - fn from(config: &EccConfig) -> Self { - Self { - q_mul_fixed_full: config.q_mul_fixed_full, - super_config: config.mul_fixed, - } - } -} - impl Config { - pub fn create_gate(&self, meta: &mut ConstraintSystem) { + pub(crate) fn configure( + meta: &mut ConstraintSystem, + super_config: super::Config, + ) -> Self { + let config = Self { + q_mul_fixed_full: meta.selector(), + super_config, + }; + + config.create_gate(meta); + + config + } + + fn create_gate(&self, meta: &mut ConstraintSystem) { // Check that each window `k` is within 3 bits meta.create_gate("Full-width fixed-base scalar mul", |meta| { let q_mul_fixed_full = meta.query_selector(self.q_mul_fixed_full); From 687e220c36a11d25c8525e364009c3df299617d0 Mon Sep 17 00:00:00 2001 From: therealyingtong Date: Tue, 30 Nov 2021 22:20:24 -0500 Subject: [PATCH 32/59] mul_fixed::short: Refactor short::Config. This commit does not result in circuit changes. --- src/circuit/gadget/ecc/chip.rs | 15 ++++----- .../gadget/ecc/chip/mul_fixed/short.rs | 31 +++++++++++-------- 2 files changed, 24 insertions(+), 22 deletions(-) diff --git a/src/circuit/gadget/ecc/chip.rs b/src/circuit/gadget/ecc/chip.rs index 230625bc..2c5dcdb2 100644 --- a/src/circuit/gadget/ecc/chip.rs +++ b/src/circuit/gadget/ecc/chip.rs @@ -147,7 +147,7 @@ pub struct EccConfig { /// Fixed-base full-width scalar multiplication mul_fixed_full: mul_fixed::full_width::Config, /// Fixed-base signed short scalar multiplication - pub q_mul_fixed_short: Selector, + mul_fixed_short: mul_fixed::short::Config, /// Canonicity checks on base field element used as scalar in fixed-base mul pub q_mul_fixed_base_field: Selector, @@ -238,6 +238,9 @@ impl EccChip { // Create gate that is only used in full-width fixed-base scalar mul. let mul_fixed_full = mul_fixed::full_width::Config::configure(meta, mul_fixed); + // Create gate that is only used in short fixed-base scalar mul. + let mul_fixed_short = mul_fixed::short::Config::configure(meta, mul_fixed); + let config = EccConfig { advices, add_incomplete, @@ -245,18 +248,12 @@ impl EccChip { mul, mul_fixed, mul_fixed_full, - q_mul_fixed_short: meta.selector(), + mul_fixed_short, q_mul_fixed_base_field: meta.selector(), witness_point, lookup_config: range_check, }; - // Create gate that is only used in short fixed-base scalar mul. - { - let short_config: mul_fixed::short::Config = (&config).into(); - short_config.create_gate(meta); - } - // Create gate that is only used in fixed-base mul using a base field element. { let base_field_config: mul_fixed::base_field_elem::Config = (&config).into(); @@ -437,7 +434,7 @@ impl EccInstructions for EccChip { magnitude_sign: (CellValue, CellValue), base: &Self::FixedPointsShort, ) -> Result<(Self::Point, Self::ScalarFixedShort), Error> { - let config: mul_fixed::short::Config = self.config().into(); + let config: mul_fixed::short::Config = self.config().mul_fixed_short; config.assign( layouter.namespace(|| format!("short fixed-base mul of {:?}", base)), magnitude_sign, diff --git a/src/circuit/gadget/ecc/chip/mul_fixed/short.rs b/src/circuit/gadget/ecc/chip/mul_fixed/short.rs index 50f3550f..d3cbc4f7 100644 --- a/src/circuit/gadget/ecc/chip/mul_fixed/short.rs +++ b/src/circuit/gadget/ecc/chip/mul_fixed/short.rs @@ -1,6 +1,6 @@ use std::{array, convert::TryInto}; -use super::super::{EccConfig, EccPoint, EccScalarFixedShort}; +use super::super::{EccPoint, EccScalarFixedShort}; use crate::{ circuit::gadget::utilities::{bool_check, copy, CellValue, Var}, constants::{ValueCommitV, L_VALUE, NUM_WINDOWS_SHORT}, @@ -13,24 +13,29 @@ use halo2::{ }; use pasta_curves::pallas; -#[derive(Clone)] +#[derive(Clone, Debug, Copy, Eq, PartialEq)] pub struct Config { // Selector used for fixed-base scalar mul with short signed exponent. q_mul_fixed_short: Selector, super_config: super::Config, } -impl From<&EccConfig> for Config { - fn from(config: &EccConfig) -> Self { - Self { - q_mul_fixed_short: config.q_mul_fixed_short, - super_config: config.mul_fixed, - } - } -} - impl Config { - pub(crate) fn create_gate(&self, meta: &mut ConstraintSystem) { + pub(crate) fn configure( + meta: &mut ConstraintSystem, + super_config: super::Config, + ) -> Self { + let config = Self { + q_mul_fixed_short: meta.selector(), + super_config, + }; + + config.create_gate(meta); + + config + } + + fn create_gate(&self, meta: &mut ConstraintSystem) { meta.create_gate("Short fixed-base mul gate", |meta| { let q_mul_fixed_short = meta.query_selector(self.q_mul_fixed_short); let y_p = meta.query_advice(self.super_config.y_p, Rotation::cur()); @@ -444,7 +449,7 @@ pub mod tests { ) -> Result<(), Error> { let column = config.advices[0]; - let short_config: super::Config = (&config).into(); + let short_config = config.mul_fixed_short; let magnitude_sign = { let magnitude = self.load_private( layouter.namespace(|| "load magnitude"), From c00ee1707e4dacb2e3cffaee6e57dce438679d06 Mon Sep 17 00:00:00 2001 From: therealyingtong Date: Tue, 30 Nov 2021 22:31:49 -0500 Subject: [PATCH 33/59] mul_fixed::base_field_elem: Refactor base_field_elem::Config. This commit does not result in circuit changes. --- src/circuit/gadget/ecc/chip.rs | 31 +++++++++---------- .../ecc/chip/mul_fixed/base_field_elem.rs | 30 ++++++++++++------ 2 files changed, 35 insertions(+), 26 deletions(-) diff --git a/src/circuit/gadget/ecc/chip.rs b/src/circuit/gadget/ecc/chip.rs index 2c5dcdb2..f20a36d2 100644 --- a/src/circuit/gadget/ecc/chip.rs +++ b/src/circuit/gadget/ecc/chip.rs @@ -11,10 +11,12 @@ use arrayvec::ArrayVec; use group::prime::PrimeCurveAffine; use halo2::{ circuit::{Chip, Layouter}, - plonk::{Advice, Column, ConstraintSystem, Error, Fixed, Selector}, + plonk::{Advice, Column, ConstraintSystem, Error, Fixed}, }; use pasta_curves::{arithmetic::CurveAffine, pallas}; +use std::convert::TryInto; + pub(super) mod add; pub(super) mod add_incomplete; pub(super) mod mul; @@ -148,8 +150,8 @@ pub struct EccConfig { mul_fixed_full: mul_fixed::full_width::Config, /// Fixed-base signed short scalar multiplication mul_fixed_short: mul_fixed::short::Config, - /// Canonicity checks on base field element used as scalar in fixed-base mul - pub q_mul_fixed_base_field: Selector, + /// Fixed-base mul using a base field element as a scalar + mul_fixed_base_field: mul_fixed::base_field_elem::Config, /// Witness point witness_point: witness_point::Config, @@ -196,11 +198,6 @@ impl EccChip { lagrange_coeffs: [Column; 8], range_check: LookupRangeCheckConfig, ) -> >::Config { - // The following columns need to be equality-enabled for their use in sub-configs: - // - // mul_fixed::base_field_element::Config: - // - [advices[6], advices[7], advices[8]]: canon_advices - // // TODO: Refactor away from `impl From for _` so that sub-configs can // equality-enable the columns they need to. for column in &advices { @@ -241,6 +238,14 @@ impl EccChip { // Create gate that is only used in short fixed-base scalar mul. let mul_fixed_short = mul_fixed::short::Config::configure(meta, mul_fixed); + // Create gate that is only used in fixed-base mul using a base field element. + let mul_fixed_base_field = mul_fixed::base_field_elem::Config::configure( + meta, + advices[6..9].try_into().unwrap(), + range_check, + mul_fixed, + ); + let config = EccConfig { advices, add_incomplete, @@ -249,17 +254,11 @@ impl EccChip { mul_fixed, mul_fixed_full, mul_fixed_short, - q_mul_fixed_base_field: meta.selector(), + mul_fixed_base_field, witness_point, lookup_config: range_check, }; - // Create gate that is only used in fixed-base mul using a base field element. - { - let base_field_config: mul_fixed::base_field_elem::Config = (&config).into(); - base_field_config.create_gate(meta); - } - config } } @@ -448,7 +447,7 @@ impl EccInstructions for EccChip { base_field_elem: CellValue, base: &Self::FixedPointsBaseField, ) -> Result { - let config: mul_fixed::base_field_elem::Config = self.config().into(); + let config = self.config().mul_fixed_base_field; config.assign( layouter.namespace(|| format!("base-field elem fixed-base mul of {:?}", base)), base_field_elem, diff --git a/src/circuit/gadget/ecc/chip/mul_fixed/base_field_elem.rs b/src/circuit/gadget/ecc/chip/mul_fixed/base_field_elem.rs index e1c7169c..bf4a0765 100644 --- a/src/circuit/gadget/ecc/chip/mul_fixed/base_field_elem.rs +++ b/src/circuit/gadget/ecc/chip/mul_fixed/base_field_elem.rs @@ -1,4 +1,4 @@ -use super::super::{EccBaseFieldElemFixed, EccConfig, EccPoint, NullifierK}; +use super::super::{EccBaseFieldElemFixed, EccPoint, NullifierK}; use super::H_BASE; use crate::{ @@ -18,6 +18,7 @@ use pasta_curves::{arithmetic::FieldExt, pallas}; use std::convert::TryInto; +#[derive(Copy, Clone, Debug, Eq, PartialEq)] pub struct Config { q_mul_fixed_base_field: Selector, canon_advices: [Column; 3], @@ -25,13 +26,22 @@ pub struct Config { super_config: super::Config, } -impl From<&EccConfig> for Config { - fn from(config: &EccConfig) -> Self { +impl Config { + pub(crate) fn configure( + meta: &mut ConstraintSystem, + canon_advices: [Column; 3], + lookup_config: LookupRangeCheckConfig, + super_config: super::Config, + ) -> Self { + for advice in canon_advices.iter() { + meta.enable_equality((*advice).into()); + } + let config = Self { - q_mul_fixed_base_field: config.q_mul_fixed_base_field, - canon_advices: [config.advices[6], config.advices[7], config.advices[8]], - lookup_config: config.lookup_config, - super_config: config.mul_fixed, + q_mul_fixed_base_field: meta.selector(), + canon_advices, + lookup_config, + super_config, }; let add_incomplete_advices = config.super_config.add_incomplete_config.advice_columns(); @@ -42,12 +52,12 @@ impl From<&EccConfig> for Config { ); } + config.create_gate(meta); + config } -} -impl Config { - pub fn create_gate(&self, meta: &mut ConstraintSystem) { + fn create_gate(&self, meta: &mut ConstraintSystem) { // Check that the base field element is canonical. meta.create_gate("Canonicity checks", |meta| { let q_mul_fixed_base_field = meta.query_selector(self.q_mul_fixed_base_field); From a09173a331394a77c004e17faa8bc0adafca8a4c Mon Sep 17 00:00:00 2001 From: therealyingtong Date: Tue, 30 Nov 2021 22:37:12 -0500 Subject: [PATCH 34/59] ecc::chip: Remove chip-level permutation. We have now refactored away from the impl From pattern so that each sub-config can equality-enable the columns they need. --- src/circuit/gadget/ecc/chip.rs | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/src/circuit/gadget/ecc/chip.rs b/src/circuit/gadget/ecc/chip.rs index f20a36d2..d4016075 100644 --- a/src/circuit/gadget/ecc/chip.rs +++ b/src/circuit/gadget/ecc/chip.rs @@ -143,9 +143,6 @@ pub struct EccConfig { /// Variable-base scalar multiplication mul: mul::Config, - /// TODO: Remove this. - pub mul_fixed: mul_fixed::Config, - /// Fixed-base full-width scalar multiplication mul_fixed_full: mul_fixed::full_width::Config, /// Fixed-base signed short scalar multiplication @@ -198,12 +195,6 @@ impl EccChip { lagrange_coeffs: [Column; 8], range_check: LookupRangeCheckConfig, ) -> >::Config { - // TODO: Refactor away from `impl From for _` so that sub-configs can - // equality-enable the columns they need to. - for column in &advices { - meta.enable_equality((*column).into()); - } - // Create witness point gate let witness_point = witness_point::Config::configure(meta, advices[0], advices[1]); // Create incomplete point addition gate @@ -246,20 +237,17 @@ impl EccChip { mul_fixed, ); - let config = EccConfig { + EccConfig { advices, add_incomplete, add, mul, - mul_fixed, mul_fixed_full, mul_fixed_short, mul_fixed_base_field, witness_point, lookup_config: range_check, - }; - - config + } } } From a38e2ff7283a56650c4e4107892c3156d8b8df19 Mon Sep 17 00:00:00 2001 From: str4d Date: Wed, 8 Dec 2021 01:00:18 +0000 Subject: [PATCH 35/59] Ensure lo and hi incomplete ranges line up The previous code assumed that `pallas::Scalar::NUM_BITS` was odd, which is true, but might not remain so after a future generalisation refactor. --- src/circuit/gadget/ecc/chip/mul.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/circuit/gadget/ecc/chip/mul.rs b/src/circuit/gadget/ecc/chip/mul.rs index eebb1a02..edb66fca 100644 --- a/src/circuit/gadget/ecc/chip/mul.rs +++ b/src/circuit/gadget/ecc/chip/mul.rs @@ -43,8 +43,8 @@ const INCOMPLETE_HI_LEN: usize = INCOMPLETE_LEN / 2; // Bits k_{254} to k_{4} inclusive are used in incomplete addition. // The `lo` half is k_{129} to k_{4} inclusive (length 126 bits). -const INCOMPLETE_LO_RANGE: Range = (INCOMPLETE_LEN / 2)..INCOMPLETE_LEN; -const INCOMPLETE_LO_LEN: usize = (INCOMPLETE_LEN / 2) + 1; +const INCOMPLETE_LO_RANGE: Range = INCOMPLETE_HI_LEN..INCOMPLETE_LEN; +const INCOMPLETE_LO_LEN: usize = INCOMPLETE_LEN - INCOMPLETE_HI_LEN; // Bits k_{3} to k_{1} inclusive are used in complete addition. // Bit k_{0} is handled separately. From 50b4600a1a9a094f670ed437960f8ae7b246c29f Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 1 Dec 2021 12:51:33 +0000 Subject: [PATCH 36/59] circuit: Remove `Copy` impl from `CellValue` We will be replacing it with `halo2::circuit::AssignedCell`, which does not impl `Copy`. --- src/circuit.rs | 16 +++---- src/circuit/gadget/ecc/chip.rs | 16 +++---- src/circuit/gadget/ecc/chip/mul.rs | 23 +++++----- src/circuit/gadget/ecc/chip/mul/complete.rs | 9 ++-- src/circuit/gadget/ecc/chip/mul/incomplete.rs | 2 +- src/circuit/gadget/ecc/chip/mul/overflow.rs | 6 +-- .../ecc/chip/mul_fixed/base_field_elem.rs | 18 ++++---- .../gadget/ecc/chip/mul_fixed/full_width.rs | 4 +- .../gadget/ecc/chip/mul_fixed/short.rs | 10 ++--- src/circuit/gadget/sinsemilla.rs | 4 +- src/circuit/gadget/sinsemilla/commit_ivk.rs | 14 +++--- src/circuit/gadget/sinsemilla/merkle/chip.rs | 6 +-- src/circuit/gadget/sinsemilla/message.rs | 4 +- src/circuit/gadget/sinsemilla/note_commit.rs | 44 ++++++++++--------- src/circuit/gadget/utilities.rs | 4 +- src/circuit/gadget/utilities/cond_swap.rs | 7 ++- .../gadget/utilities/decompose_running_sum.rs | 6 +-- .../gadget/utilities/lookup_range_check.rs | 6 +-- 18 files changed, 105 insertions(+), 94 deletions(-) diff --git a/src/circuit.rs b/src/circuit.rs index 43dd2663..e0542c90 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -405,7 +405,7 @@ impl plonk::Circuit for Circuit { leaf_pos: self.pos, path, }; - let leaf = *cm_old.extract_p().inner(); + let leaf = cm_old.extract_p().inner().clone(); merkle_inputs.calculate_root(layouter.namespace(|| "MerkleCRH"), leaf)? }; @@ -454,7 +454,7 @@ impl plonk::Circuit for Circuit { let (commitment, _) = { let value_commit_v = ValueCommitV::get(); let value_commit_v = FixedPointShort::from_inner(ecc_chip.clone(), value_commit_v); - value_commit_v.mul(layouter.namespace(|| "[v_net] ValueCommitV"), v_net)? + value_commit_v.mul(layouter.namespace(|| "[v_net] ValueCommitV"), v_net.clone())? }; // blind = [rcv] ValueCommitR @@ -481,7 +481,7 @@ impl plonk::Circuit for Circuit { let nf_old = { // hash_old = poseidon_hash(nk, rho_old) let hash_old = { - let poseidon_message = [nk, rho_old]; + let poseidon_message = [nk.clone(), rho_old.clone()]; let poseidon_hasher = PoseidonHash::<_, _, poseidon::P128Pow5T3, _, 3, 2>::init( config.poseidon_chip(), layouter.namespace(|| "Poseidon init"), @@ -581,7 +581,7 @@ impl plonk::Circuit for Circuit { config.sinsemilla_chip_1(), ecc_chip.clone(), layouter.namespace(|| "CommitIvk"), - *ak.extract_p().inner(), + ak.extract_p().inner().clone(), nk, rivk, )? @@ -619,7 +619,7 @@ impl plonk::Circuit for Circuit { config.ecc_chip(), g_d_old.inner(), pk_d_old.inner(), - v_old, + v_old.clone(), rho_old, psi_old, rcm_old, @@ -675,8 +675,8 @@ impl plonk::Circuit for Circuit { config.ecc_chip(), g_d_new.inner(), pk_d_new.inner(), - v_new, - *nf_old.inner(), + v_new.clone(), + nf_old.inner().clone(), psi_new, rcm_new, )?; @@ -694,7 +694,7 @@ impl plonk::Circuit for Circuit { |mut region| { copy(&mut region, || "v_old", config.advices[0], 0, &v_old)?; copy(&mut region, || "v_new", config.advices[1], 0, &v_new)?; - let (magnitude, sign) = v_net; + let (magnitude, sign) = v_net.clone(); copy( &mut region, || "v_net magnitude", diff --git a/src/circuit/gadget/ecc/chip.rs b/src/circuit/gadget/ecc/chip.rs index d4016075..e299f0c9 100644 --- a/src/circuit/gadget/ecc/chip.rs +++ b/src/circuit/gadget/ecc/chip.rs @@ -26,7 +26,7 @@ pub(super) mod witness_point; /// A curve point represented in affine (x, y) coordinates, or the /// identity represented as (0, 0). /// Each coordinate is assigned to a cell. -#[derive(Copy, Clone, Debug)] +#[derive(Clone, Debug)] pub struct EccPoint { /// x-coordinate x: CellValue, @@ -62,12 +62,12 @@ impl EccPoint { /// The cell containing the affine short-Weierstrass x-coordinate, /// or 0 for the zero point. pub fn x(&self) -> CellValue { - self.x + self.x.clone() } /// The cell containing the affine short-Weierstrass y-coordinate, /// or 0 for the zero point. pub fn y(&self) -> CellValue { - self.y + self.y.clone() } #[cfg(test)] @@ -78,7 +78,7 @@ impl EccPoint { /// A non-identity point represented in affine (x, y) coordinates. /// Each coordinate is assigned to a cell. -#[derive(Copy, Clone, Debug)] +#[derive(Clone, Debug)] pub struct NonIdentityEccPoint { /// x-coordinate x: CellValue, @@ -110,11 +110,11 @@ impl NonIdentityEccPoint { } /// The cell containing the affine short-Weierstrass x-coordinate. pub fn x(&self) -> CellValue { - self.x + self.x.clone() } /// The cell containing the affine short-Weierstrass y-coordinate. pub fn y(&self) -> CellValue { - self.y + self.y.clone() } } @@ -298,7 +298,7 @@ struct EccBaseFieldElemFixed { impl EccBaseFieldElemFixed { fn base_field_elem(&self) -> CellValue { - self.base_field_elem + self.base_field_elem.clone() } } @@ -396,7 +396,7 @@ impl EccInstructions for EccChip { let config = self.config().mul; config.assign( layouter.namespace(|| "variable-base scalar mul"), - *scalar, + scalar.clone(), base, ) } diff --git a/src/circuit/gadget/ecc/chip/mul.rs b/src/circuit/gadget/ecc/chip/mul.rs index edb66fca..bf1bae58 100644 --- a/src/circuit/gadget/ecc/chip/mul.rs +++ b/src/circuit/gadget/ecc/chip/mul.rs @@ -175,7 +175,7 @@ impl Config { let offset = 0; // Case `base` into an `EccPoint` for later use. - let base_point: EccPoint = (*base).into(); + let base_point: EccPoint = base.clone().into(); // Decompose `k = alpha + t_q` bitwise (big-endian bit order). let bits = decompose_for_scalar_mul(alpha.value()); @@ -211,7 +211,7 @@ impl Config { offset, base, bits_incomplete_hi, - (X(acc.x), Y(acc.y), z_init), + (X(acc.x), Y(acc.y), z_init.clone()), )?; // Double-and-add (incomplete addition) for the `lo` half of the scalar decomposition @@ -221,7 +221,7 @@ impl Config { offset, base, bits_incomplete_lo, - (x_a, y_a, *z), + (x_a, y_a, z.clone()), )?; // Move from incomplete addition to complete addition. @@ -245,7 +245,7 @@ impl Config { &base_point, x_a, y_a, - *z, + z.clone(), )? }; @@ -253,8 +253,8 @@ impl Config { let offset = offset + COMPLETE_RANGE.len() * 2; // Process the least significant bit - let z_1 = zs_complete.last().unwrap(); - let (result, z_0) = self.process_lsb(&mut region, offset, base, acc, *z_1, lsb)?; + let z_1 = zs_complete.last().unwrap().clone(); + let (result, z_0) = self.process_lsb(&mut region, offset, base, acc, z_1, lsb)?; #[cfg(test)] // Check that the correct multiple is obtained. @@ -292,8 +292,11 @@ impl Config { }, )?; - self.overflow_config - .overflow_check(layouter.namespace(|| "overflow check"), alpha, &zs)?; + self.overflow_config.overflow_check( + layouter.namespace(|| "overflow check"), + alpha.clone(), + &zs, + )?; Ok((result, alpha)) } @@ -416,7 +419,7 @@ impl Deref for X { } } -#[derive(Copy, Clone, Debug)] +#[derive(Clone, Debug)] // `y`-coordinate of the accumulator. struct Y(CellValue); impl Deref for Y { @@ -427,7 +430,7 @@ impl Deref for Y { } } -#[derive(Copy, Clone, Debug)] +#[derive(Clone, Debug)] // Cumulative sum `z` used to decompose the scalar. struct Z(CellValue); impl Deref for Z { diff --git a/src/circuit/gadget/ecc/chip/mul/complete.rs b/src/circuit/gadget/ecc/chip/mul/complete.rs index 20767f51..476efd80 100644 --- a/src/circuit/gadget/ecc/chip/mul/complete.rs +++ b/src/circuit/gadget/ecc/chip/mul/complete.rs @@ -106,7 +106,7 @@ impl Config { } // Use x_a, y_a output from incomplete addition - let mut acc = EccPoint { x: *x_a, y: *y_a }; + let mut acc = EccPoint { x: x_a.0, y: y_a.0 }; // Copy running sum `z` from incomplete addition let mut z = { @@ -148,7 +148,7 @@ impl Config { )?; Z(CellValue::new(z_cell, z_val)) }; - zs.push(z); + zs.push(z.clone()); // Assign `y_p` for complete addition. let y_p = { @@ -176,7 +176,10 @@ impl Config { }; // U = P if the bit is set; U = -P is the bit is not set. - let U = EccPoint { x: base.x, y: y_p }; + let U = EccPoint { + x: base.x.clone(), + y: y_p, + }; // Acc + U let tmp_acc = self diff --git a/src/circuit/gadget/ecc/chip/mul/incomplete.rs b/src/circuit/gadget/ecc/chip/mul/incomplete.rs index 3a980bd7..a17925d0 100644 --- a/src/circuit/gadget/ecc/chip/mul/incomplete.rs +++ b/src/circuit/gadget/ecc/chip/mul/incomplete.rs @@ -251,7 +251,7 @@ impl Config { || z_val.ok_or(Error::Synthesis), )?; z = CellValue::new(z_cell, z_val); - zs.push(Z(z)); + zs.push(Z(z.clone())); // Assign `x_p`, `y_p` region.assign_advice( diff --git a/src/circuit/gadget/ecc/chip/mul/overflow.rs b/src/circuit/gadget/ecc/chip/mul/overflow.rs index 57a94a41..f331615b 100644 --- a/src/circuit/gadget/ecc/chip/mul/overflow.rs +++ b/src/circuit/gadget/ecc/chip/mul/overflow.rs @@ -107,7 +107,7 @@ impl Config { // In the overflow check gate, we check that s is properly derived // from alpha and k_254. let s = { - let k_254 = *zs[254]; + let k_254 = zs[254].clone(); let s_val = alpha .value() .zip(k_254.value()) @@ -130,7 +130,7 @@ impl Config { // Subtract the first 130 low bits of s = alpha + k_254 â‹… 2^130 // using thirteen 10-bit lookups, s_{0..=129} let s_minus_lo_130 = - self.s_minus_lo_130(layouter.namespace(|| "decompose s_{0..=129}"), s)?; + self.s_minus_lo_130(layouter.namespace(|| "decompose s_{0..=129}"), s.clone())?; layouter.assign_region( || "overflow check", @@ -223,6 +223,6 @@ impl Config { false, )?; // (s - (2^0 s_0 + 2^1 s_1 + ... + 2^129 s_129)) / 2^130 - Ok(zs[zs.len() - 1]) + Ok(zs[zs.len() - 1].clone()) } } diff --git a/src/circuit/gadget/ecc/chip/mul_fixed/base_field_elem.rs b/src/circuit/gadget/ecc/chip/mul_fixed/base_field_elem.rs index bf4a0765..06283905 100644 --- a/src/circuit/gadget/ecc/chip/mul_fixed/base_field_elem.rs +++ b/src/circuit/gadget/ecc/chip/mul_fixed/base_field_elem.rs @@ -173,13 +173,13 @@ impl Config { let running_sum = self.super_config.running_sum_config.copy_decompose( &mut region, offset, - scalar, + scalar.clone(), true, constants::L_ORCHARD_BASE, constants::NUM_WINDOWS, )?; EccBaseFieldElemFixed { - base_field_elem: running_sum[0], + base_field_elem: running_sum[0].clone(), running_sum: (*running_sum).as_slice().try_into().unwrap(), } }; @@ -203,8 +203,8 @@ impl Config { || "Base-field elem fixed-base mul (complete addition)", |mut region| { self.super_config.add_config.assign_region( - &mul_b.into(), - &acc.into(), + &mul_b.clone().into(), + &acc.clone().into(), 0, &mut region, ) @@ -249,9 +249,9 @@ impl Config { // => z_13_alpha_0_prime = 0 // let (alpha, running_sum) = (scalar.base_field_elem, &scalar.running_sum); - let z_43_alpha = running_sum[43]; - let z_44_alpha = running_sum[44]; - let z_84_alpha = running_sum[84]; + let z_43_alpha = running_sum[43].clone(); + let z_44_alpha = running_sum[44].clone(); + let z_84_alpha = running_sum[84].clone(); // α_0 = α - z_84_alpha * 2^252 let alpha_0 = alpha @@ -275,9 +275,9 @@ impl Config { 13, false, )?; - let alpha_0_prime = zs[0]; + let alpha_0_prime = zs[0].clone(); - (alpha_0_prime, zs[13]) + (alpha_0_prime, zs[13].clone()) }; layouter.assign_region( diff --git a/src/circuit/gadget/ecc/chip/mul_fixed/full_width.rs b/src/circuit/gadget/ecc/chip/mul_fixed/full_width.rs index 6db138b0..03e976ab 100644 --- a/src/circuit/gadget/ecc/chip/mul_fixed/full_width.rs +++ b/src/circuit/gadget/ecc/chip/mul_fixed/full_width.rs @@ -149,8 +149,8 @@ impl Config { || "Full-width fixed-base mul (last window, complete addition)", |mut region| { self.super_config.add_config.assign_region( - &mul_b.into(), - &acc.into(), + &mul_b.clone().into(), + &acc.clone().into(), 0, &mut region, ) diff --git a/src/circuit/gadget/ecc/chip/mul_fixed/short.rs b/src/circuit/gadget/ecc/chip/mul_fixed/short.rs index d3cbc4f7..319511e8 100644 --- a/src/circuit/gadget/ecc/chip/mul_fixed/short.rs +++ b/src/circuit/gadget/ecc/chip/mul_fixed/short.rs @@ -82,7 +82,7 @@ impl Config { let running_sum = self.super_config.running_sum_config.copy_decompose( region, offset, - magnitude, + magnitude.clone(), true, L_VALUE, NUM_WINDOWS_SHORT, @@ -107,7 +107,7 @@ impl Config { let offset = 0; // Decompose the scalar - let scalar = self.decompose(&mut region, offset, magnitude_sign)?; + let scalar = self.decompose(&mut region, offset, magnitude_sign.clone())?; let (acc, mul_b) = self.super_config.assign_region_inner::( &mut region, @@ -128,8 +128,8 @@ impl Config { let offset = 0; // Add to the cumulative sum to get `[magnitude]B`. let magnitude_mul = self.super_config.add_config.assign_region( - &mul_b.into(), - &acc.into(), + &mul_b.clone().into(), + &acc.clone().into(), offset, &mut region, )?; @@ -149,7 +149,7 @@ impl Config { // Copy last window to `u` column. // (Although the last window is not a `u` value; we are copying it into the `u` // column because there is an available cell there.) - let z_21 = scalar.running_sum[21]; + let z_21 = scalar.running_sum[21].clone(); copy( &mut region, || "last_window", diff --git a/src/circuit/gadget/sinsemilla.rs b/src/circuit/gadget/sinsemilla.rs index 91fe3381..20d8259a 100644 --- a/src/circuit/gadget/sinsemilla.rs +++ b/src/circuit/gadget/sinsemilla.rs @@ -32,7 +32,7 @@ pub trait SinsemillaInstructions + Clone + Debug + Eq, { fn inner(&self) -> SinsemillaChip::MessagePiece { - self.inner + self.inner.clone() } } diff --git a/src/circuit/gadget/sinsemilla/commit_ivk.rs b/src/circuit/gadget/sinsemilla/commit_ivk.rs index dd3a8be3..f089472e 100644 --- a/src/circuit/gadget/sinsemilla/commit_ivk.rs +++ b/src/circuit/gadget/sinsemilla/commit_ivk.rs @@ -337,8 +337,8 @@ impl CommitIvkConfig { domain.short_commit(layouter.namespace(|| "Hash ak||nk"), message, rivk)? }; - let z13_a = zs[0][13]; - let z13_c = zs[2][13]; + let z13_a = zs[0][13].clone(); + let z13_c = zs[2][13].clone(); let (a_prime, z13_a_prime) = self.ak_canonicity( layouter.namespace(|| "ak canonicity"), @@ -347,7 +347,7 @@ impl CommitIvkConfig { let (b2_c_prime, z14_b2_c_prime) = self.nk_canonicity( layouter.namespace(|| "nk canonicity"), - b_2, + b_2.clone(), c.inner().cell_value(), )?; @@ -406,10 +406,10 @@ impl CommitIvkConfig { 13, false, )?; - let a_prime = zs[0]; + let a_prime = zs[0].clone(); assert_eq!(zs.len(), 14); // [z_0, z_1, ..., z13_a] - Ok((a_prime, zs[13])) + Ok((a_prime, zs[13].clone())) } #[allow(clippy::type_complexity)] @@ -443,10 +443,10 @@ impl CommitIvkConfig { 14, false, )?; - let b2_c_prime = zs[0]; + let b2_c_prime = zs[0].clone(); assert_eq!(zs.len(), 15); // [z_0, z_1, ..., z14] - Ok((b2_c_prime, zs[14])) + Ok((b2_c_prime, zs[14].clone())) } // Assign cells for the canonicity gate. diff --git a/src/circuit/gadget/sinsemilla/merkle/chip.rs b/src/circuit/gadget/sinsemilla/merkle/chip.rs index ce25531e..46107c86 100644 --- a/src/circuit/gadget/sinsemilla/merkle/chip.rs +++ b/src/circuit/gadget/sinsemilla/merkle/chip.rs @@ -257,10 +257,10 @@ impl MerkleInstructions std:: /// /// The piece must fit within a base field element, which means its length /// cannot exceed the base field's `NUM_BITS`. -#[derive(Copy, Clone, Debug)] +#[derive(Clone, Debug)] pub struct MessagePiece { cell_value: CellValue, /// The number of K-bit words in this message piece. @@ -62,6 +62,6 @@ impl MessagePiece { } pub fn cell_value(&self) -> CellValue { - self.cell_value + self.cell_value.clone() } } diff --git a/src/circuit/gadget/sinsemilla/note_commit.rs b/src/circuit/gadget/sinsemilla/note_commit.rs index 72f4b785..6ad2e821 100644 --- a/src/circuit/gadget/sinsemilla/note_commit.rs +++ b/src/circuit/gadget/sinsemilla/note_commit.rs @@ -738,13 +738,13 @@ impl NoteCommitConfig { )? }; - let z13_a = zs[0][13]; - let z13_c = zs[2][13]; - let z1_d = zs[3][1]; - let z13_f = zs[5][13]; - let z1_g = zs[6][1]; - let g_2 = z1_g; - let z13_g = zs[6][13]; + let z13_a = zs[0][13].clone(); + let z13_c = zs[2][13].clone(); + let z1_d = zs[3][1].clone(); + let z13_f = zs[5][13].clone(); + let z1_g = zs[6][1].clone(); + let g_2 = z1_g.clone(); + let z13_g = zs[6][13].clone(); let (a_prime, z13_a_prime) = self.canon_bitshift_130( layouter.namespace(|| "x(g_d) canonicity"), @@ -753,18 +753,18 @@ impl NoteCommitConfig { let (b3_c_prime, z14_b3_c_prime) = self.pkd_x_canonicity( layouter.namespace(|| "x(pk_d) canonicity"), - b_3, + b_3.clone(), c.inner().cell_value(), )?; let (e1_f_prime, z14_e1_f_prime) = self.rho_canonicity( layouter.namespace(|| "rho canonicity"), - e_1, + e_1.clone(), f.inner().cell_value(), )?; let (g1_g2_prime, z13_g1_g2_prime) = - self.psi_canonicity(layouter.namespace(|| "psi canonicity"), g_1, g_2)?; + self.psi_canonicity(layouter.namespace(|| "psi canonicity"), g_1.clone(), g_2)?; let gate_cells = GateCells { a: a.inner().cell_value(), @@ -841,10 +841,10 @@ impl NoteCommitConfig { 13, false, )?; - let a_prime = zs[0]; + let a_prime = zs[0].clone(); assert_eq!(zs.len(), 14); // [z_0, z_1, ..., z_13] - Ok((a_prime, zs[13])) + Ok((a_prime, zs[13].clone())) } // Check canonicity of `x(pk_d)` encoding @@ -880,10 +880,10 @@ impl NoteCommitConfig { 14, false, )?; - let b3_c_prime = zs[0]; + let b3_c_prime = zs[0].clone(); assert_eq!(zs.len(), 15); // [z_0, z_1, ..., z_13, z_14] - Ok((b3_c_prime, zs[14])) + Ok((b3_c_prime, zs[14].clone())) } #[allow(clippy::type_complexity)] @@ -920,10 +920,10 @@ impl NoteCommitConfig { 14, false, )?; - let e1_f_prime = zs[0]; + let e1_f_prime = zs[0].clone(); assert_eq!(zs.len(), 15); // [z_0, z_1, ..., z_13, z_14] - Ok((e1_f_prime, zs[14])) + Ok((e1_f_prime, zs[14].clone())) } // Check canonicity of `psi` encoding @@ -957,10 +957,10 @@ impl NoteCommitConfig { 13, false, )?; - let g1_g2_prime = zs[0]; + let g1_g2_prime = zs[0].clone(); assert_eq!(zs.len(), 14); // [z_0, z_1, ..., z_13] - Ok((g1_g2_prime, zs[13])) + Ok((g1_g2_prime, zs[13].clone())) } // Check canonicity of y-coordinate given its LSB as a value. @@ -1010,13 +1010,15 @@ impl NoteCommitConfig { 25, true, )?; - (zs[0], zs[1], zs[13]) + (zs[0].clone(), zs[1].clone(), zs[13].clone()) }; // Decompose j_prime = j + 2^130 - t_P using 13 ten-bit lookups. // We can reuse the canon_bitshift_130 logic here. - let (j_prime, z13_j_prime) = - self.canon_bitshift_130(layouter.namespace(|| "j_prime = j + 2^130 - t_P"), j)?; + let (j_prime, z13_j_prime) = self.canon_bitshift_130( + layouter.namespace(|| "j_prime = j + 2^130 - t_P"), + j.clone(), + )?; /* diff --git a/src/circuit/gadget/utilities.rs b/src/circuit/gadget/utilities.rs index 20378274..3bfed1b9 100644 --- a/src/circuit/gadget/utilities.rs +++ b/src/circuit/gadget/utilities.rs @@ -13,14 +13,14 @@ pub(crate) mod decompose_running_sum; pub(crate) mod lookup_range_check; /// A variable representing a field element. -#[derive(Copy, Clone, Debug)] +#[derive(Clone, Debug)] pub struct CellValue { cell: Cell, value: Option, } /// Trait for a variable in the circuit. -pub trait Var: Copy + Clone + std::fmt::Debug { +pub trait Var: Clone + std::fmt::Debug { /// Construct a new variable. fn new(cell: Cell, value: Option) -> Self; diff --git a/src/circuit/gadget/utilities/cond_swap.rs b/src/circuit/gadget/utilities/cond_swap.rs index 6eb0a33e..365ba500 100644 --- a/src/circuit/gadget/utilities/cond_swap.rs +++ b/src/circuit/gadget/utilities/cond_swap.rs @@ -252,8 +252,11 @@ mod tests { // Load the pair and the swap flag into the circuit. let a = chip.load_private(layouter.namespace(|| "a"), config.a, self.a)?; // Return the swapped pair. - let swapped_pair = - chip.swap(layouter.namespace(|| "swap"), (a, self.b), self.swap)?; + let swapped_pair = chip.swap( + layouter.namespace(|| "swap"), + (a.clone(), self.b), + self.swap, + )?; if let Some(swap) = self.swap { if swap { diff --git a/src/circuit/gadget/utilities/decompose_running_sum.rs b/src/circuit/gadget/utilities/decompose_running_sum.rs index c5f6823e..43e4c9b9 100644 --- a/src/circuit/gadget/utilities/decompose_running_sum.rs +++ b/src/circuit/gadget/utilities/decompose_running_sum.rs @@ -179,7 +179,7 @@ impl }; // Initialize empty vector to store running sum values [z_0, ..., z_W]. - let mut zs: Vec> = vec![z_0]; + let mut zs: Vec> = vec![z_0.clone()]; let mut z = z_0; // Assign running sum `z_{i+1}` = (z_i - k_i) / (2^K) for i = 0..=n-1. @@ -205,7 +205,7 @@ impl // Update `z`. z = z_next; - zs.push(z); + zs.push(z.clone()); } assert_eq!(zs.len(), num_windows + 1); @@ -284,7 +284,7 @@ mod tests { WORD_NUM_BITS, NUM_WINDOWS, )?; - let alpha = zs[0]; + let alpha = zs[0].clone(); let offset = offset + NUM_WINDOWS + 1; diff --git a/src/circuit/gadget/utilities/lookup_range_check.rs b/src/circuit/gadget/utilities/lookup_range_check.rs index 4a2c6d85..65ef4b59 100644 --- a/src/circuit/gadget/utilities/lookup_range_check.rs +++ b/src/circuit/gadget/utilities/lookup_range_check.rs @@ -223,7 +223,7 @@ impl LookupRangeCheckConfig } }; - let mut zs = vec![element]; + let mut zs = vec![element.clone()]; // Assign cumulative sum such that // z_i = 2^{K}â‹…z_{i + 1} + a_i @@ -256,7 +256,7 @@ impl LookupRangeCheckConfig CellValue::new(z_cell, z_val) }; - zs.push(z); + zs.push(z.clone()); } if strict { @@ -316,7 +316,7 @@ impl LookupRangeCheckConfig CellValue::new(cell, element) }; - self.short_range_check(&mut region, element, num_bits)?; + self.short_range_check(&mut region, element.clone(), num_bits)?; Ok(element) }, From e99fc92e4b97d752f40244d705eaa4d81c7902f4 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 1 Dec 2021 12:59:37 +0000 Subject: [PATCH 37/59] circuit: Use `Field::is_zero_vartime` --- src/circuit/gadget/ecc/chip.rs | 7 ++++--- src/circuit/gadget/ecc/chip/add.rs | 6 +++--- src/circuit/gadget/ecc/chip/add_incomplete.rs | 5 +++-- src/circuit/gadget/ecc/chip/mul/incomplete.rs | 4 ++-- src/circuit/gadget/ecc/chip/mul/overflow.rs | 2 +- src/circuit/gadget/sinsemilla/chip/hash_to_point.rs | 2 +- 6 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/circuit/gadget/ecc/chip.rs b/src/circuit/gadget/ecc/chip.rs index e299f0c9..e354ca66 100644 --- a/src/circuit/gadget/ecc/chip.rs +++ b/src/circuit/gadget/ecc/chip.rs @@ -8,6 +8,7 @@ use crate::{ }; use arrayvec::ArrayVec; +use ff::Field; use group::prime::PrimeCurveAffine; use halo2::{ circuit::{Chip, Layouter}, @@ -50,7 +51,7 @@ impl EccPoint { pub fn point(&self) -> Option { match (self.x.value(), self.y.value()) { (Some(x), Some(y)) => { - if x == pallas::Base::zero() && y == pallas::Base::zero() { + if x.is_zero_vartime() && y.is_zero_vartime() { Some(pallas::Affine::identity()) } else { Some(pallas::Affine::from_xy(x, y).unwrap()) @@ -72,7 +73,7 @@ impl EccPoint { #[cfg(test)] fn is_identity(&self) -> Option { - self.x.value().map(|x| x == pallas::Base::zero()) + self.x.value().map(|x| x.is_zero_vartime()) } } @@ -102,7 +103,7 @@ impl NonIdentityEccPoint { pub fn point(&self) -> Option { match (self.x.value(), self.y.value()) { (Some(x), Some(y)) => { - assert!(x != pallas::Base::zero() && y != pallas::Base::zero()); + assert!(!x.is_zero_vartime() && !y.is_zero_vartime()); Some(pallas::Affine::from_xy(x, y).unwrap()) } _ => None, diff --git a/src/circuit/gadget/ecc/chip/add.rs b/src/circuit/gadget/ecc/chip/add.rs index 9e10d02c..023a678b 100644 --- a/src/circuit/gadget/ecc/chip/add.rs +++ b/src/circuit/gadget/ecc/chip/add.rs @@ -300,7 +300,7 @@ impl Config { // know that x_q != x_p in this branch. (y_q - y_p) * alpha } else { - if y_p != pallas::Base::zero() { + if !y_p.is_zero_vartime() { // 3(x_p)^2 let three_x_p_sq = pallas::Base::from_u64(3) * x_p.square(); // 1 / 2(y_p) @@ -327,10 +327,10 @@ impl Config { .zip(lambda) .map(|((((x_p, y_p), x_q), y_q), lambda)| { { - if x_p == pallas::Base::zero() { + if x_p.is_zero_vartime() { // 0 + Q = Q (x_q, y_q) - } else if x_q == pallas::Base::zero() { + } else if x_q.is_zero_vartime() { // P + 0 = P (x_p, y_p) } else if (x_q == x_p) && (y_q == -y_p) { diff --git a/src/circuit/gadget/ecc/chip/add_incomplete.rs b/src/circuit/gadget/ecc/chip/add_incomplete.rs index 30b74e0d..c1c02828 100644 --- a/src/circuit/gadget/ecc/chip/add_incomplete.rs +++ b/src/circuit/gadget/ecc/chip/add_incomplete.rs @@ -1,6 +1,7 @@ use std::{array, collections::HashSet}; use super::{copy, CellValue, NonIdentityEccPoint, Var}; +use ff::Field; use group::Curve; use halo2::{ circuit::Region, @@ -96,9 +97,9 @@ impl Config { .zip(y_q) .map(|(((x_p, y_p), x_q), y_q)| { // P is point at infinity - if (x_p == pallas::Base::zero() && y_p == pallas::Base::zero()) + if (x_p.is_zero_vartime() && y_p.is_zero_vartime()) // Q is point at infinity - || (x_q == pallas::Base::zero() && y_q == pallas::Base::zero()) + || (x_q.is_zero_vartime() && y_q.is_zero_vartime()) // x_p = x_q || (x_p == x_q) { diff --git a/src/circuit/gadget/ecc/chip/mul/incomplete.rs b/src/circuit/gadget/ecc/chip/mul/incomplete.rs index a17925d0..4ccd817d 100644 --- a/src/circuit/gadget/ecc/chip/mul/incomplete.rs +++ b/src/circuit/gadget/ecc/chip/mul/incomplete.rs @@ -195,9 +195,9 @@ impl Config { if let (Some(x_a), Some(y_a), Some(x_p), Some(y_p)) = (x_a, y_a, x_p, y_p) { // A is point at infinity - if (x_p == pallas::Base::zero() && y_p == pallas::Base::zero()) + if (x_p.is_zero_vartime() && y_p.is_zero_vartime()) // Q is point at infinity - || (x_a == pallas::Base::zero() && y_a == pallas::Base::zero()) + || (x_a.is_zero_vartime() && y_a.is_zero_vartime()) // x_p = x_a || (x_p == x_a) { diff --git a/src/circuit/gadget/ecc/chip/mul/overflow.rs b/src/circuit/gadget/ecc/chip/mul/overflow.rs index f331615b..0f5f480a 100644 --- a/src/circuit/gadget/ecc/chip/mul/overflow.rs +++ b/src/circuit/gadget/ecc/chip/mul/overflow.rs @@ -155,7 +155,7 @@ impl Config { // Witness η = inv0(z_130), where inv0(x) = 0 if x = 0, 1/x otherwise { let eta = zs[130].value().map(|z_130| { - if z_130 == pallas::Base::zero() { + if z_130.is_zero_vartime() { pallas::Base::zero() } else { z_130.invert().unwrap() diff --git a/src/circuit/gadget/sinsemilla/chip/hash_to_point.rs b/src/circuit/gadget/sinsemilla/chip/hash_to_point.rs index 81c7dc3c..60b8f23c 100644 --- a/src/circuit/gadget/sinsemilla/chip/hash_to_point.rs +++ b/src/circuit/gadget/sinsemilla/chip/hash_to_point.rs @@ -149,7 +149,7 @@ impl SinsemillaChip { if let Some(x_a) = x_a.value() { if let Some(y_a) = y_a.value() { - if x_a == pallas::Base::zero() || y_a == pallas::Base::zero() { + if x_a.is_zero_vartime() || y_a.is_zero_vartime() { return Err(Error::Synthesis); } } From 5cb838f1a254ba1499af5edaa8100fe6c92e3e3c Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 1 Dec 2021 23:52:25 +0000 Subject: [PATCH 38/59] circuit: Remove `Copy` impl from `poseidon::pow5::StateWord` We will be making it a newtype around `halo2::circuit::AssignedCell`, which does not impl `Copy`. --- src/circuit/gadget/poseidon.rs | 21 +++++++++++++++++---- src/circuit/gadget/poseidon/pow5.rs | 6 +++--- src/primitives/poseidon.rs | 9 +++++++-- 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/src/circuit/gadget/poseidon.rs b/src/circuit/gadget/poseidon.rs index 96e5917d..dba40b5d 100644 --- a/src/circuit/gadget/poseidon.rs +++ b/src/circuit/gadget/poseidon.rs @@ -1,6 +1,7 @@ //! Gadget and chips for the Poseidon algebraic hash function. use std::array; +use std::convert::TryInto; use std::fmt; use halo2::{ @@ -20,7 +21,7 @@ pub trait PoseidonInstructions, const T: usize, Chip { /// Variable representing the word over which the Poseidon permutation operates. - type Word: Copy + fmt::Debug + From> + Into>; + type Word: Clone + fmt::Debug + From> + Into>; /// Applies the Poseidon permutation to the given state. fn permute( @@ -82,7 +83,7 @@ impl< { /// The word contained in this gadget. pub fn inner(&self) -> PoseidonChip::Word { - self.inner + self.inner.clone() } /// Construct a [`Word`] gadget from the inner word. @@ -144,7 +145,13 @@ impl< chip.initial_state(&mut layouter, &domain) .map(|state| Duplex { chip, - sponge: Sponge::Absorbing([None; RATE]), + sponge: Sponge::Absorbing( + (0..RATE) + .map(|_| None) + .collect::>() + .try_into() + .unwrap(), + ), state, domain, }) @@ -205,7 +212,13 @@ impl< } // We've already squeezed out all available elements - self.sponge = Sponge::Absorbing([None; RATE]); + self.sponge = Sponge::Absorbing( + (0..RATE) + .map(|_| None) + .collect::>() + .try_into() + .unwrap(), + ); } } } diff --git a/src/circuit/gadget/poseidon/pow5.rs b/src/circuit/gadget/poseidon/pow5.rs index f6829791..ba314fe3 100644 --- a/src/circuit/gadget/poseidon/pow5.rs +++ b/src/circuit/gadget/poseidon/pow5.rs @@ -341,7 +341,7 @@ impl, const WIDTH: usize, const RATE: usize // Load the input and padding into this region. let load_input_word = |i: usize| { - let (constraint_var, value) = match (input[i], padding_values[i]) { + let (constraint_var, value) = match (input[i].clone(), padding_values[i]) { (Some(word), None) => (word.var, word.value), (None, Some(padding_value)) => { let padding_var = region.assign_fixed( @@ -395,7 +395,7 @@ impl, const WIDTH: usize, const RATE: usize fn get_output(state: &State) -> SpongeState { state[..RATE] .iter() - .map(|word| Some(*word)) + .map(|word| Some(word.clone())) .collect::>() .try_into() .unwrap() @@ -403,7 +403,7 @@ impl, const WIDTH: usize, const RATE: usize } /// A word in the Poseidon state. -#[derive(Clone, Copy, Debug)] +#[derive(Clone, Debug)] pub struct StateWord { var: Cell, value: Option, diff --git a/src/primitives/poseidon.rs b/src/primitives/poseidon.rs index 8078fac2..1afe5cbe 100644 --- a/src/primitives/poseidon.rs +++ b/src/primitives/poseidon.rs @@ -1,6 +1,7 @@ //! The Poseidon algebraic hash function. use std::array; +use std::convert::TryInto; use std::fmt; use std::iter; use std::marker::PhantomData; @@ -147,9 +148,13 @@ pub(crate) enum Sponge { Squeezing(SpongeState), } -impl Sponge { +impl Sponge { pub(crate) fn absorb(val: F) -> Self { - let mut input = [None; RATE]; + let mut input: [Option; RATE] = (0..RATE) + .map(|_| None) + .collect::>() + .try_into() + .unwrap(); input[0] = Some(val); Sponge::Absorbing(input) } From 9b41a063633e4f81b1cc65f4fa830bc91332c25f Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 2 Dec 2021 00:10:00 +0000 Subject: [PATCH 39/59] Migrate to halo2 version with `AssignedCell` We change `CellValue` into a typedef of `AssignedCell` to simplify the migration in this commit. The migration from `CellValue` to `AssignedCell` requires several other changes: - `::value()` returned `Option`, whereas `AssignedCell::::value()` returns `Option<&F>`. This means we need to dereference, use `Option::cloned`, or alter functions to take `&F` arguments. - `StateWord` in the Poseidon chip has been changed to a newtype around `AssignedCell` (the chip was written before `CellValue` existed). --- Cargo.toml | 2 +- benches/poseidon.rs | 2 +- src/circuit/gadget/ecc/chip.rs | 4 +- src/circuit/gadget/ecc/chip/add.rs | 8 +- src/circuit/gadget/ecc/chip/mul.rs | 4 +- src/circuit/gadget/ecc/chip/mul/complete.rs | 10 +- src/circuit/gadget/ecc/chip/mul/incomplete.rs | 8 +- .../ecc/chip/mul_fixed/base_field_elem.rs | 1 - .../gadget/ecc/chip/mul_fixed/full_width.rs | 2 +- .../gadget/ecc/chip/mul_fixed/short.rs | 10 +- src/circuit/gadget/poseidon/pow5.rs | 95 +++++++++---------- .../gadget/sinsemilla/chip/hash_to_point.rs | 4 +- src/circuit/gadget/sinsemilla/commit_ivk.rs | 6 +- src/circuit/gadget/sinsemilla/merkle.rs | 4 +- src/circuit/gadget/sinsemilla/merkle/chip.rs | 4 +- src/circuit/gadget/sinsemilla/message.rs | 4 +- src/circuit/gadget/sinsemilla/note_commit.rs | 6 +- src/circuit/gadget/utilities.rs | 36 +++---- src/circuit/gadget/utilities/cond_swap.rs | 38 ++++---- .../gadget/utilities/decompose_running_sum.rs | 2 +- .../gadget/utilities/lookup_range_check.rs | 7 +- src/constants/util.rs | 4 +- 22 files changed, 122 insertions(+), 139 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2b38917e..365804a5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -90,4 +90,4 @@ debug = true [patch.crates-io] zcash_note_encryption = { git = "https://github.com/zcash/librustzcash.git", rev = "35e75420657599fdc701cb45704878eb3fa2e59a" } incrementalmerkletree = { git = "https://github.com/zcash/incrementalmerkletree.git", rev = "b7bd6246122a6e9ace8edb51553fbf5228906cbb" } -halo2 = { git = "https://github.com/zcash/halo2.git", rev = "8bfc58b7c76ae83ba5a9ed7ecdfe0ddfd40ed571" } +halo2 = { git = "https://github.com/zcash/halo2.git", rev = "afd7bc5469674cd08eae1634225fd02706a36a4f" } diff --git a/benches/poseidon.rs b/benches/poseidon.rs index 4f40d9a6..7591e144 100644 --- a/benches/poseidon.rs +++ b/benches/poseidon.rs @@ -121,7 +121,7 @@ where 0, || self.output.ok_or(Error::Synthesis), )?; - region.constrain_equal(output.cell(), expected_var) + region.constrain_equal(output.cell(), expected_var.cell()) }, ) } diff --git a/src/circuit/gadget/ecc/chip.rs b/src/circuit/gadget/ecc/chip.rs index e354ca66..92ad5f4c 100644 --- a/src/circuit/gadget/ecc/chip.rs +++ b/src/circuit/gadget/ecc/chip.rs @@ -54,7 +54,7 @@ impl EccPoint { if x.is_zero_vartime() && y.is_zero_vartime() { Some(pallas::Affine::identity()) } else { - Some(pallas::Affine::from_xy(x, y).unwrap()) + Some(pallas::Affine::from_xy(*x, *y).unwrap()) } } _ => None, @@ -104,7 +104,7 @@ impl NonIdentityEccPoint { match (self.x.value(), self.y.value()) { (Some(x), Some(y)) => { assert!(!x.is_zero_vartime() && !y.is_zero_vartime()); - Some(pallas::Affine::from_xy(x, y).unwrap()) + Some(pallas::Affine::from_xy(*x, *y).unwrap()) } _ => None, } diff --git a/src/circuit/gadget/ecc/chip/add.rs b/src/circuit/gadget/ecc/chip/add.rs index 023a678b..510ea6a6 100644 --- a/src/circuit/gadget/ecc/chip/add.rs +++ b/src/circuit/gadget/ecc/chip/add.rs @@ -248,7 +248,7 @@ impl Config { let gamma = x_q; let delta = y_q + y_p; - let mut inverses = [alpha, beta, gamma, delta]; + let mut inverses = [alpha, *beta, *gamma, delta]; inverses.batch_invert(); inverses }); @@ -329,11 +329,11 @@ impl Config { { if x_p.is_zero_vartime() { // 0 + Q = Q - (x_q, y_q) + (*x_q, *y_q) } else if x_q.is_zero_vartime() { // P + 0 = P - (x_p, y_p) - } else if (x_q == x_p) && (y_q == -y_p) { + (*x_p, *y_p) + } else if (x_q == x_p) && (*y_q == -y_p) { // P + (-P) maps to (0,0) (pallas::Base::zero(), pallas::Base::zero()) } else { diff --git a/src/circuit/gadget/ecc/chip/mul.rs b/src/circuit/gadget/ecc/chip/mul.rs index bf1bae58..fc99adfe 100644 --- a/src/circuit/gadget/ecc/chip/mul.rs +++ b/src/circuit/gadget/ecc/chip/mul.rs @@ -364,7 +364,7 @@ impl Config { // If `lsb` is 0, return `Acc + (-P)`. If `lsb` is 1, simply return `Acc + 0`. let x = if let Some(lsb) = lsb { if !lsb { - base.x.value() + base.x.value().cloned() } else { Some(pallas::Base::zero()) } @@ -441,7 +441,7 @@ impl Deref for Z { } } -fn decompose_for_scalar_mul(scalar: Option) -> Vec> { +fn decompose_for_scalar_mul(scalar: Option<&pallas::Base>) -> Vec> { let bitstring = scalar.map(|scalar| { // We use `k = scalar + t_q` in the double-and-add algorithm, where // the scalar field `F_q = 2^254 + t_q`. diff --git a/src/circuit/gadget/ecc/chip/mul/complete.rs b/src/circuit/gadget/ecc/chip/mul/complete.rs index 476efd80..12c1d525 100644 --- a/src/circuit/gadget/ecc/chip/mul/complete.rs +++ b/src/circuit/gadget/ecc/chip/mul/complete.rs @@ -161,10 +161,12 @@ impl Config { )?; // If the bit is set, use `y`; if the bit is not set, use `-y` - let y_p = base_y - .value() - .zip(k.as_ref()) - .map(|(base_y, k)| if !k { -base_y } else { base_y }); + let y_p = + base_y + .value() + .cloned() + .zip(k.as_ref()) + .map(|(base_y, k)| if !k { -base_y } else { base_y }); let y_p_cell = region.assign_advice( || "y_p", diff --git a/src/circuit/gadget/ecc/chip/mul/incomplete.rs b/src/circuit/gadget/ecc/chip/mul/incomplete.rs index 4ccd817d..17874ec2 100644 --- a/src/circuit/gadget/ecc/chip/mul/incomplete.rs +++ b/src/circuit/gadget/ecc/chip/mul/incomplete.rs @@ -190,8 +190,8 @@ impl Config { assert_eq!(bits.len(), NUM_BITS); // Handle exceptional cases - let (x_p, y_p) = (base.x.value(), base.y.value()); - let (x_a, y_a) = (acc.0.value(), acc.1.value()); + let (x_p, y_p) = (base.x.value().cloned(), base.y.value().cloned()); + let (x_a, y_a) = (acc.0.value().cloned(), acc.1.value().cloned()); if let (Some(x_a), Some(y_a), Some(x_p), Some(y_p)) = (x_a, y_a, x_p, y_p) { // A is point at infinity @@ -229,7 +229,7 @@ impl Config { let x_a = copy(region, || "starting x_a", self.x_a, offset + 1, &acc.0)?; let y_a = copy(region, || "starting y_a", self.lambda1, offset, &acc.1)?; - (x_a, y_a.value(), z) + (x_a, y_a.value().cloned(), z) }; // Increase offset by 1; we used row 0 for initializing `z`. @@ -313,7 +313,7 @@ impl Config { .zip(x_r) .map(|((lambda2, x_a), x_r)| lambda2.square() - x_a - x_r); y_a = lambda2 - .zip(x_a.value()) + .zip(x_a.value().cloned()) .zip(x_a_new) .zip(y_a) .map(|(((lambda2, x_a), x_a_new), y_a)| lambda2 * (x_a - x_a_new) - y_a); diff --git a/src/circuit/gadget/ecc/chip/mul_fixed/base_field_elem.rs b/src/circuit/gadget/ecc/chip/mul_fixed/base_field_elem.rs index 06283905..dc421e53 100644 --- a/src/circuit/gadget/ecc/chip/mul_fixed/base_field_elem.rs +++ b/src/circuit/gadget/ecc/chip/mul_fixed/base_field_elem.rs @@ -4,7 +4,6 @@ use super::H_BASE; use crate::{ circuit::gadget::utilities::{ bitrange_subset, copy, lookup_range_check::LookupRangeCheckConfig, range_check, CellValue, - Var, }, constants::{self, T_P}, primitives::sinsemilla, diff --git a/src/circuit/gadget/ecc/chip/mul_fixed/full_width.rs b/src/circuit/gadget/ecc/chip/mul_fixed/full_width.rs index 03e976ab..7e632ff0 100644 --- a/src/circuit/gadget/ecc/chip/mul_fixed/full_width.rs +++ b/src/circuit/gadget/ecc/chip/mul_fixed/full_width.rs @@ -85,7 +85,7 @@ impl Config { // Decompose scalar into `k-bit` windows let scalar_windows: Option> = scalar.map(|scalar| { util::decompose_word::( - scalar, + &scalar, SCALAR_NUM_BITS, constants::FIXED_BASE_WINDOW_SIZE, ) diff --git a/src/circuit/gadget/ecc/chip/mul_fixed/short.rs b/src/circuit/gadget/ecc/chip/mul_fixed/short.rs index 319511e8..7982d998 100644 --- a/src/circuit/gadget/ecc/chip/mul_fixed/short.rs +++ b/src/circuit/gadget/ecc/chip/mul_fixed/short.rs @@ -160,10 +160,10 @@ impl Config { // Conditionally negate `y`-coordinate let y_val = if let Some(sign) = sign.value() { - if sign == -pallas::Base::one() { - magnitude_mul.y.value().map(|y: pallas::Base| -y) + if sign == &-pallas::Base::one() { + magnitude_mul.y.value().cloned().map(|y: pallas::Base| -y) } else { - magnitude_mul.y.value() + magnitude_mul.y.value().cloned() } } else { None @@ -199,7 +199,7 @@ impl Config { if let (Some(magnitude), Some(sign)) = (scalar.magnitude.value(), scalar.sign.value()) { let magnitude_is_valid = - magnitude <= pallas::Base::from_u64(0xFFFF_FFFF_FFFF_FFFFu64); + magnitude <= &pallas::Base::from_u64(0xFFFF_FFFF_FFFF_FFFFu64); let sign_is_valid = sign * sign == pallas::Base::one(); if magnitude_is_valid && sign_is_valid { let base: super::OrchardFixedBases = base.clone().into(); @@ -211,7 +211,7 @@ impl Config { let magnitude = pallas::Scalar::from_bytes(&magnitude.to_bytes()).unwrap(); - let sign = if sign == pallas::Base::one() { + let sign = if sign == &pallas::Base::one() { pallas::Scalar::one() } else { -pallas::Scalar::one() diff --git a/src/circuit/gadget/poseidon/pow5.rs b/src/circuit/gadget/poseidon/pow5.rs index ba314fe3..fb8a9042 100644 --- a/src/circuit/gadget/poseidon/pow5.rs +++ b/src/circuit/gadget/poseidon/pow5.rs @@ -3,13 +3,13 @@ use std::iter; use halo2::{ arithmetic::FieldExt, - circuit::{Cell, Chip, Layouter, Region}, + circuit::{AssignedCell, Cell, Chip, Layouter, Region}, plonk::{Advice, Column, ConstraintSystem, Error, Expression, Fixed, Selector}, poly::Rotation, }; use super::{PoseidonDuplexInstructions, PoseidonInstructions}; -use crate::circuit::gadget::utilities::{CellValue, Var}; +use crate::circuit::gadget::utilities::Var; use crate::primitives::poseidon::{Domain, Mds, Spec, SpongeState, State}; /// Configuration for a [`Pow5Chip`]. @@ -288,10 +288,7 @@ impl, const WIDTH: usize, const RATE: usize 0, value, )?; - state.push(StateWord { - var, - value: Some(value), - }); + state.push(StateWord(var)); Ok(()) }; @@ -323,15 +320,15 @@ impl, const WIDTH: usize, const RATE: usize // Load the initial state into this region. let load_state_word = |i: usize| { - let value = initial_state[i].value; + let value = initial_state[i].0.value().cloned(); let var = region.assign_advice( || format!("load state_{}", i), config.state[i], 0, || value.ok_or(Error::Synthesis), )?; - region.constrain_equal(initial_state[i].var, var)?; - Ok(StateWord { var, value }) + region.constrain_equal(initial_state[i].0.cell(), var.cell())?; + Ok(StateWord(var)) }; let initial_state: Result, Error> = (0..WIDTH).map(load_state_word).collect(); @@ -342,7 +339,7 @@ impl, const WIDTH: usize, const RATE: usize // Load the input and padding into this region. let load_input_word = |i: usize| { let (constraint_var, value) = match (input[i].clone(), padding_values[i]) { - (Some(word), None) => (word.var, word.value), + (Some(word), None) => (word.0.cell(), word.0.value().cloned()), (None, Some(padding_value)) => { let padding_var = region.assign_fixed( || format!("load pad_{}", i), @@ -350,7 +347,7 @@ impl, const WIDTH: usize, const RATE: usize 1, || Ok(padding_value), )?; - (padding_var, Some(padding_value)) + (padding_var.cell(), Some(padding_value)) } _ => panic!("Input and padding don't match"), }; @@ -360,30 +357,31 @@ impl, const WIDTH: usize, const RATE: usize 1, || value.ok_or(Error::Synthesis), )?; - region.constrain_equal(constraint_var, var)?; + region.constrain_equal(constraint_var, var.cell())?; - Ok(StateWord { var, value }) + Ok(StateWord(var)) }; let input: Result, Error> = (0..RATE).map(load_input_word).collect(); let input = input?; // Constrain the output. let constrain_output_word = |i: usize| { - let value = initial_state[i].value.and_then(|initial_word| { + let value = initial_state[i].0.value().and_then(|initial_word| { input .get(i) - .map(|word| word.value) + .map(|word| word.0.value().cloned()) // The capacity element is never altered by the input. .unwrap_or_else(|| Some(F::zero())) - .map(|input_word| initial_word + input_word) + .map(|input_word| *initial_word + input_word) }); - let var = region.assign_advice( - || format!("load output_{}", i), - config.state[i], - 2, - || value.ok_or(Error::Synthesis), - )?; - Ok(StateWord { var, value }) + region + .assign_advice( + || format!("load output_{}", i), + config.state[i], + 2, + || value.ok_or(Error::Synthesis), + ) + .map(StateWord) }; let output: Result, Error> = (0..WIDTH).map(constrain_output_word).collect(); @@ -404,34 +402,31 @@ impl, const WIDTH: usize, const RATE: usize /// A word in the Poseidon state. #[derive(Clone, Debug)] -pub struct StateWord { - var: Cell, - value: Option, -} +pub struct StateWord(AssignedCell); -impl From> for CellValue { - fn from(state_word: StateWord) -> CellValue { - CellValue::new(state_word.var, state_word.value) +impl From> for AssignedCell { + fn from(state_word: StateWord) -> AssignedCell { + state_word.0 } } -impl From> for StateWord { - fn from(cell_value: CellValue) -> StateWord { - StateWord::new(cell_value.cell(), cell_value.value()) +impl From> for StateWord { + fn from(cell_value: AssignedCell) -> StateWord { + StateWord(cell_value) } } impl Var for StateWord { - fn new(var: Cell, value: Option) -> Self { - Self { var, value } + fn new(var: AssignedCell, value: Option) -> Self { + Self(var) } fn cell(&self) -> Cell { - self.var + self.0.cell() } fn value(&self) -> Option { - self.value + self.0.value().cloned() } } @@ -447,11 +442,11 @@ impl Pow5State { offset: usize, ) -> Result { Self::round(region, config, round, offset, config.s_full, |_| { - let q = self - .0 - .iter() - .enumerate() - .map(|(idx, word)| word.value.map(|v| v + config.round_constants[round][idx])); + let q = self.0.iter().enumerate().map(|(idx, word)| { + word.0 + .value() + .map(|v| *v + config.round_constants[round][idx]) + }); let r: Option> = q.map(|q| q.map(|q| q.pow(&config.alpha))).collect(); let m = &config.m_reg; let state = m.iter().map(|m_i| { @@ -475,7 +470,7 @@ impl Pow5State { ) -> Result { Self::round(region, config, round, offset, config.s_partial, |region| { let m = &config.m_reg; - let p: Option> = self.0.iter().map(|word| word.value).collect(); + let p: Option> = self.0.iter().map(|word| word.0.value().cloned()).collect(); let r: Option> = p.map(|p| { let r_0 = (p[0] + config.round_constants[round][0]).pow(&config.alpha); @@ -547,15 +542,15 @@ impl Pow5State { initial_state: &State, WIDTH>, ) -> Result { let load_state_word = |i: usize| { - let value = initial_state[i].value; + let value = initial_state[i].0.value().cloned(); let var = region.assign_advice( || format!("load state_{}", i), config.state[i], 0, || value.ok_or(Error::Synthesis), )?; - region.constrain_equal(initial_state[i].var, var)?; - Ok(StateWord { var, value }) + region.constrain_equal(initial_state[i].0.cell(), var.cell())?; + Ok(StateWord(var)) }; let state: Result, _> = (0..WIDTH).map(load_state_word).collect(); @@ -597,7 +592,7 @@ impl Pow5State { offset + 1, || value.ok_or(Error::Synthesis), )?; - Ok(StateWord { var, value }) + Ok(StateWord(var)) }; let next_state: Result, _> = (0..WIDTH).map(next_state_word).collect(); @@ -674,7 +669,7 @@ mod tests { 0, || value.ok_or(Error::Synthesis), )?; - Ok(StateWord { var, value }) + Ok(StateWord(var)) }; let state: Result, Error> = (0..WIDTH).map(state_word).collect(); @@ -713,7 +708,7 @@ mod tests { 0, || Ok(expected_final_state[i]), )?; - region.constrain_equal(final_state[i].var, var) + region.constrain_equal(final_state[i].0.cell(), var.cell()) }; for i in 0..(WIDTH) { @@ -821,7 +816,7 @@ mod tests { 0, || self.output.ok_or(Error::Synthesis), )?; - region.constrain_equal(output.cell(), expected_var) + region.constrain_equal(output.cell(), expected_var.cell()) }, ) } diff --git a/src/circuit/gadget/sinsemilla/chip/hash_to_point.rs b/src/circuit/gadget/sinsemilla/chip/hash_to_point.rs index 60b8f23c..8c8aff5b 100644 --- a/src/circuit/gadget/sinsemilla/chip/hash_to_point.rs +++ b/src/circuit/gadget/sinsemilla/chip/hash_to_point.rs @@ -142,7 +142,7 @@ impl SinsemillaChip { .chunks(K) .fold(Q.to_curve(), |acc, chunk| (acc + S(chunk)) + acc); let actual_point = - pallas::Affine::from_xy(x_a.value().unwrap(), y_a.value().unwrap()).unwrap(); + pallas::Affine::from_xy(*x_a.value().unwrap(), *y_a.value().unwrap()).unwrap(); assert_eq!(expected_point.to_affine(), actual_point); } } @@ -270,7 +270,7 @@ impl SinsemillaChip { offset, || piece.field_elem().ok_or(Error::Synthesis), )?; - region.constrain_equal(piece.cell(), cell)?; + region.constrain_equal(piece.cell(), cell.cell())?; zs.push(CellValue::new(cell, piece.field_elem())); // Assign cumulative sum such that for 0 <= i < n, diff --git a/src/circuit/gadget/sinsemilla/commit_ivk.rs b/src/circuit/gadget/sinsemilla/commit_ivk.rs index f089472e..a10f8c0c 100644 --- a/src/circuit/gadget/sinsemilla/commit_ivk.rs +++ b/src/circuit/gadget/sinsemilla/commit_ivk.rs @@ -8,7 +8,7 @@ use pasta_curves::{arithmetic::FieldExt, pallas}; use crate::{ circuit::gadget::{ ecc::{chip::EccChip, X}, - utilities::{bitrange_subset, bool_check, copy, CellValue, Var}, + utilities::{bitrange_subset, bool_check, copy, CellValue}, }, constants::T_P, }; @@ -641,7 +641,7 @@ mod tests { ecc::chip::{EccChip, EccConfig}, sinsemilla::chip::SinsemillaChip, utilities::{ - lookup_range_check::LookupRangeCheckConfig, CellValue, UtilitiesInstructions, Var, + lookup_range_check::LookupRangeCheckConfig, CellValue, UtilitiesInstructions, }, }, constants::{COMMIT_IVK_PERSONALIZATION, L_ORCHARD_BASE, T_Q}, @@ -803,7 +803,7 @@ mod tests { .unwrap() }; - assert_eq!(expected_ivk, ivk.inner().value().unwrap()); + assert_eq!(&expected_ivk, ivk.inner().value().unwrap()); Ok(()) } diff --git a/src/circuit/gadget/sinsemilla/merkle.rs b/src/circuit/gadget/sinsemilla/merkle.rs index a5d24d48..c28f83e4 100644 --- a/src/circuit/gadget/sinsemilla/merkle.rs +++ b/src/circuit/gadget/sinsemilla/merkle.rs @@ -139,7 +139,7 @@ pub mod tests { use crate::{ circuit::gadget::{ sinsemilla::chip::{SinsemillaChip, SinsemillaHashDomains}, - utilities::{lookup_range_check::LookupRangeCheckConfig, UtilitiesInstructions, Var}, + utilities::{lookup_range_check::LookupRangeCheckConfig, UtilitiesInstructions}, }, constants::MERKLE_DEPTH_ORCHARD, note::commitment::ExtractedNoteCommitment, @@ -266,7 +266,7 @@ pub mod tests { }; // Check the computed final root against the expected final root. - assert_eq!(computed_final_root.value().unwrap(), final_root.inner()); + assert_eq!(computed_final_root.value().unwrap(), &final_root.inner()); } Ok(()) diff --git a/src/circuit/gadget/sinsemilla/merkle/chip.rs b/src/circuit/gadget/sinsemilla/merkle/chip.rs index 46107c86..310a7ae2 100644 --- a/src/circuit/gadget/sinsemilla/merkle/chip.rs +++ b/src/circuit/gadget/sinsemilla/merkle/chip.rs @@ -15,7 +15,7 @@ use crate::{ circuit::gadget::utilities::{ bitrange_subset, cond_swap::{CondSwapChip, CondSwapConfig, CondSwapInstructions}, - copy, CellValue, UtilitiesInstructions, Var, + copy, CellValue, UtilitiesInstructions, }, constants::{L_ORCHARD_BASE, MERKLE_DEPTH_ORCHARD}, primitives::sinsemilla, @@ -185,7 +185,7 @@ impl MerkleInstructions { } impl MessagePiece { - pub fn new(cell: Cell, field_elem: Option, num_words: usize) -> Self { + pub fn new(cell: CellValue, field_elem: Option, num_words: usize) -> Self { assert!(num_words * K < F::NUM_BITS as usize); let cell_value = CellValue::new(cell, field_elem); Self { @@ -58,7 +58,7 @@ impl MessagePiece { } pub fn field_elem(&self) -> Option { - self.cell_value.value() + self.cell_value.value().cloned() } pub fn cell_value(&self) -> CellValue { diff --git a/src/circuit/gadget/sinsemilla/note_commit.rs b/src/circuit/gadget/sinsemilla/note_commit.rs index 6ad2e821..c50b9fdd 100644 --- a/src/circuit/gadget/sinsemilla/note_commit.rs +++ b/src/circuit/gadget/sinsemilla/note_commit.rs @@ -530,8 +530,10 @@ impl NoteCommitConfig { psi: CellValue, rcm: Option, ) -> Result, Error> { - let (gd_x, gd_y) = (g_d.x().value(), g_d.y().value()); - let (pkd_x, pkd_y) = (pk_d.x().value(), pk_d.y().value()); + let (gd_x, gd_y) = (g_d.x(), g_d.y()); + let (pkd_x, pkd_y) = (pk_d.x(), pk_d.y()); + let (gd_x, gd_y) = (gd_x.value(), gd_y.value()); + let (pkd_x, pkd_y) = (pkd_x.value(), pkd_y.value()); let value_val = value.value(); let rho_val = rho.value(); let psi_val = psi.value(); diff --git a/src/circuit/gadget/utilities.rs b/src/circuit/gadget/utilities.rs index 3bfed1b9..12997ce1 100644 --- a/src/circuit/gadget/utilities.rs +++ b/src/circuit/gadget/utilities.rs @@ -2,7 +2,7 @@ use ff::PrimeFieldBits; use halo2::{ - circuit::{Cell, Layouter, Region}, + circuit::{AssignedCell, Cell, Layouter, Region}, plonk::{Advice, Column, Error, Expression}, }; use pasta_curves::arithmetic::FieldExt; @@ -13,16 +13,12 @@ pub(crate) mod decompose_running_sum; pub(crate) mod lookup_range_check; /// A variable representing a field element. -#[derive(Clone, Debug)] -pub struct CellValue { - cell: Cell, - value: Option, -} +pub type CellValue = AssignedCell; /// Trait for a variable in the circuit. pub trait Var: Clone + std::fmt::Debug { /// Construct a new variable. - fn new(cell: Cell, value: Option) -> Self; + fn new(cell: AssignedCell, value: Option) -> Self; /// The cell at which this variable was allocated. fn cell(&self) -> Cell; @@ -32,16 +28,16 @@ pub trait Var: Clone + std::fmt::Debug { } impl Var for CellValue { - fn new(cell: Cell, value: Option) -> Self { - Self { cell, value } + fn new(cell: AssignedCell, _value: Option) -> Self { + cell } fn cell(&self) -> Cell { - self.cell + self.cell() } fn value(&self) -> Option { - self.value + self.value().cloned() } } @@ -90,13 +86,9 @@ where A: Fn() -> AR, AR: Into, { - let cell = region.assign_advice(annotation, column, offset, || { - copy.value.ok_or(Error::Synthesis) - })?; - - region.constrain_equal(cell, copy.cell)?; - - Ok(CellValue::new(cell, copy.value)) + // Temporarily implement `copy()` in terms of `AssignedCell::copy_advice`. + // We will remove this in a subsequent commit. + copy.copy_advice(annotation, region, column, offset) } pub(crate) fn transpose_option_array( @@ -126,7 +118,7 @@ pub fn ternary(a: Expression, b: Expression, c: Expression /// Takes a specified subsequence of the little-endian bit representation of a field element. /// The bits are numbered from 0 for the LSB. -pub fn bitrange_subset(field_elem: F, bitrange: Range) -> F { +pub fn bitrange_subset(field_elem: &F, bitrange: Range) -> F { assert!(bitrange.end <= F::NUM_BITS as usize); let bits: Vec = field_elem @@ -251,7 +243,7 @@ mod tests { { let field_elem = pallas::Base::rand(); let bitrange = 0..(pallas::Base::NUM_BITS as usize); - let subset = bitrange_subset(field_elem, bitrange); + let subset = bitrange_subset(&field_elem, bitrange); assert_eq!(field_elem, subset); } @@ -259,7 +251,7 @@ mod tests { { let field_elem = pallas::Base::rand(); let bitrange = 0..0; - let subset = bitrange_subset(field_elem, bitrange); + let subset = bitrange_subset(&field_elem, bitrange); assert_eq!(pallas::Base::zero(), subset); } @@ -286,7 +278,7 @@ mod tests { let subsets = ranges .iter() - .map(|range| bitrange_subset(field_elem, range.clone())) + .map(|range| bitrange_subset(&field_elem, range.clone())) .collect::>(); let mut sum = subsets[0]; diff --git a/src/circuit/gadget/utilities/cond_swap.rs b/src/circuit/gadget/utilities/cond_swap.rs index 365ba500..e979048e 100644 --- a/src/circuit/gadget/utilities/cond_swap.rs +++ b/src/circuit/gadget/utilities/cond_swap.rs @@ -98,39 +98,33 @@ impl CondSwapInstructions for CondSwapChip { // Conditionally swap a let a_swapped = { let a_swapped = a - .value - .zip(b.value) + .value() + .zip(b.value()) .zip(swap) - .map(|((a, b), swap)| if swap { b } else { a }); - let a_swapped_cell = region.assign_advice( + .map(|((a, b), swap)| if swap { b } else { a }) + .cloned(); + region.assign_advice( || "a_swapped", config.a_swapped, 0, || a_swapped.ok_or(Error::Synthesis), - )?; - CellValue { - cell: a_swapped_cell, - value: a_swapped, - } + )? }; // Conditionally swap b let b_swapped = { let b_swapped = a - .value - .zip(b.value) + .value() + .zip(b.value()) .zip(swap) - .map(|((a, b), swap)| if swap { a } else { b }); - let b_swapped_cell = region.assign_advice( + .map(|((a, b), swap)| if swap { a } else { b }) + .cloned(); + region.assign_advice( || "b_swapped", config.b_swapped, 0, || b_swapped.ok_or(Error::Synthesis), - )?; - CellValue { - cell: b_swapped_cell, - value: b_swapped, - } + )? }; // Return swapped pair @@ -261,12 +255,12 @@ mod tests { if let Some(swap) = self.swap { if swap { // Check that `a` and `b` have been swapped - assert_eq!(swapped_pair.0.value.unwrap(), self.b.unwrap()); - assert_eq!(swapped_pair.1.value.unwrap(), a.value.unwrap()); + assert_eq!(swapped_pair.0.value().unwrap(), &self.b.unwrap()); + assert_eq!(swapped_pair.1.value().unwrap(), a.value().unwrap()); } else { // Check that `a` and `b` have not been swapped - assert_eq!(swapped_pair.0.value.unwrap(), a.value.unwrap()); - assert_eq!(swapped_pair.1.value.unwrap(), self.b.unwrap()); + assert_eq!(swapped_pair.0.value().unwrap(), a.value().unwrap()); + assert_eq!(swapped_pair.1.value().unwrap(), &self.b.unwrap()); } } diff --git a/src/circuit/gadget/utilities/decompose_running_sum.rs b/src/circuit/gadget/utilities/decompose_running_sum.rs index 43e4c9b9..6b2da383 100644 --- a/src/circuit/gadget/utilities/decompose_running_sum.rs +++ b/src/circuit/gadget/utilities/decompose_running_sum.rs @@ -193,7 +193,7 @@ impl let z_next_val = z .value() .zip(word) - .map(|(z_cur_val, word)| (z_cur_val - word) * two_pow_k_inv); + .map(|(z_cur_val, word)| (*z_cur_val - word) * two_pow_k_inv); let cell = region.assign_advice( || format!("z_{:?}", i + 1), self.z, diff --git a/src/circuit/gadget/utilities/lookup_range_check.rs b/src/circuit/gadget/utilities/lookup_range_check.rs index 65ef4b59..0f535721 100644 --- a/src/circuit/gadget/utilities/lookup_range_check.rs +++ b/src/circuit/gadget/utilities/lookup_range_check.rs @@ -244,7 +244,7 @@ impl LookupRangeCheckConfig let z_val = z .value() .zip(*word) - .map(|(z, word)| (z - word) * inv_two_pow_k); + .map(|(z, word)| (*z - word) * inv_two_pow_k); // Assign z_next let z_cell = region.assign_advice( @@ -344,7 +344,7 @@ impl LookupRangeCheckConfig // Assign shifted `element * 2^{K - num_bits}` let shifted = element.value().map(|element| { let shift = F::from_u64(1 << (K - num_bits)); - element * shift + *element * shift }); region.assign_advice( @@ -369,7 +369,6 @@ impl LookupRangeCheckConfig #[cfg(test)] mod tests { - use super::super::Var; use super::LookupRangeCheckConfig; use crate::primitives::sinsemilla::{INV_TWO_POW_K, K}; @@ -468,7 +467,7 @@ mod tests { for (expected_z, z) in expected_zs.into_iter().zip(zs.iter()) { if let Some(z) = z.value() { - assert_eq!(expected_z, z); + assert_eq!(&expected_z, z); } } } diff --git a/src/constants/util.rs b/src/constants/util.rs index bdb84901..b325091c 100644 --- a/src/constants/util.rs +++ b/src/constants/util.rs @@ -10,7 +10,7 @@ use halo2::arithmetic::{CurveAffine, FieldExt}; /// We are returning a `Vec` which means the window size is limited to /// <= 8 bits. pub fn decompose_word( - word: F, + word: &F, word_num_bits: usize, window_num_bits: usize, ) -> Vec { @@ -86,7 +86,7 @@ mod tests { window_num_bits in 1u8..9 ) { // Get decomposition into `window_num_bits` bits - let decomposed = decompose_word(scalar, pallas::Scalar::NUM_BITS as usize, window_num_bits as usize); + let decomposed = decompose_word(&scalar, pallas::Scalar::NUM_BITS as usize, window_num_bits as usize); // Flatten bits let bits = decomposed From 3079800f42e85c8bb17ad0109a70cfbdaa88e8b9 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 2 Dec 2021 01:10:00 +0000 Subject: [PATCH 40/59] Remove `Var::new` trait method As the underlying `Region` methods now return `AssignedCell` instead of `Cell`, we can simplify all the places where we then constructed a `CellValue` struct. --- benches/poseidon.rs | 10 +-- src/circuit.rs | 7 +- src/circuit/gadget/ecc/chip.rs | 2 +- src/circuit/gadget/ecc/chip/add.rs | 6 +- src/circuit/gadget/ecc/chip/add_incomplete.rs | 6 +- src/circuit/gadget/ecc/chip/mul.rs | 24 +++--- src/circuit/gadget/ecc/chip/mul/complete.rs | 9 +-- src/circuit/gadget/ecc/chip/mul/incomplete.rs | 23 +++--- src/circuit/gadget/ecc/chip/mul/overflow.rs | 7 +- src/circuit/gadget/ecc/chip/mul_fixed.rs | 15 ++-- .../gadget/ecc/chip/mul_fixed/full_width.rs | 4 +- .../gadget/ecc/chip/mul_fixed/short.rs | 4 +- src/circuit/gadget/ecc/chip/witness_point.rs | 7 +- src/circuit/gadget/poseidon/pow5.rs | 14 +--- src/circuit/gadget/sinsemilla/chip.rs | 2 +- .../gadget/sinsemilla/chip/hash_to_point.rs | 17 ++-- src/circuit/gadget/sinsemilla/message.rs | 5 +- src/circuit/gadget/sinsemilla/note_commit.rs | 77 ++++++++----------- src/circuit/gadget/utilities.rs | 24 +++--- src/circuit/gadget/utilities/cond_swap.rs | 17 ++-- .../gadget/utilities/decompose_running_sum.rs | 22 +++--- .../gadget/utilities/lookup_range_check.rs | 38 ++++----- 22 files changed, 134 insertions(+), 206 deletions(-) diff --git a/benches/poseidon.rs b/benches/poseidon.rs index 7591e144..480be0b9 100644 --- a/benches/poseidon.rs +++ b/benches/poseidon.rs @@ -12,10 +12,7 @@ use halo2::{ use pasta_curves::{pallas, vesta}; use orchard::{ - circuit::gadget::{ - poseidon::{Hash, Pow5Chip, Pow5Config}, - utilities::{CellValue, Var}, - }, + circuit::gadget::poseidon::{Hash, Pow5Chip, Pow5Config}, primitives::poseidon::{self, ConstantLength, Spec}, }; use std::convert::TryInto; @@ -91,13 +88,12 @@ where |mut region| { let message_word = |i: usize| { let value = self.message.map(|message_vals| message_vals[i]); - let cell = region.assign_advice( + region.assign_advice( || format!("load message_{}", i), config.input[i], 0, || value.ok_or(Error::Synthesis), - )?; - Ok(CellValue::new(cell, value)) + ) }; let message: Result, Error> = (0..L).map(message_word).collect(); diff --git a/src/circuit.rs b/src/circuit.rs index e0542c90..7d6c8b69 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -50,7 +50,7 @@ use gadget::{ }, note_commit::NoteCommitConfig, }, - utilities::{copy, CellValue, UtilitiesInstructions, Var}, + utilities::{copy, CellValue, UtilitiesInstructions}, }; use std::convert::TryInto; @@ -520,13 +520,12 @@ impl plonk::Circuit for Circuit { .value() .zip(psi_old.value()) .map(|(hash_old, psi_old)| hash_old + psi_old); - let cell = region.assign_advice( + region.assign_advice( || "poseidon_hash(nk, rho_old) + psi_old", config.advices[6], 0, || scalar_val.ok_or(plonk::Error::Synthesis), - )?; - Ok(CellValue::new(cell, scalar_val)) + ) }, )?; diff --git a/src/circuit/gadget/ecc/chip.rs b/src/circuit/gadget/ecc/chip.rs index 92ad5f4c..d50bf98a 100644 --- a/src/circuit/gadget/ecc/chip.rs +++ b/src/circuit/gadget/ecc/chip.rs @@ -1,7 +1,7 @@ use super::EccInstructions; use crate::{ circuit::gadget::utilities::{ - copy, lookup_range_check::LookupRangeCheckConfig, CellValue, UtilitiesInstructions, Var, + copy, lookup_range_check::LookupRangeCheckConfig, CellValue, UtilitiesInstructions, }, constants::{self, NullifierK, OrchardFixedBasesFull, ValueCommitV}, primitives::sinsemilla, diff --git a/src/circuit/gadget/ecc/chip/add.rs b/src/circuit/gadget/ecc/chip/add.rs index 510ea6a6..aec2f615 100644 --- a/src/circuit/gadget/ecc/chip/add.rs +++ b/src/circuit/gadget/ecc/chip/add.rs @@ -1,6 +1,6 @@ use std::array; -use super::{copy, CellValue, EccPoint, Var}; +use super::{copy, EccPoint}; use ff::{BatchInvert, Field}; use halo2::{ circuit::Region, @@ -365,8 +365,8 @@ impl Config { )?; let result = EccPoint { - x: CellValue::::new(x_r_cell, x_r), - y: CellValue::::new(y_r_cell, y_r), + x: x_r_cell, + y: y_r_cell, }; #[cfg(test)] diff --git a/src/circuit/gadget/ecc/chip/add_incomplete.rs b/src/circuit/gadget/ecc/chip/add_incomplete.rs index c1c02828..d466056d 100644 --- a/src/circuit/gadget/ecc/chip/add_incomplete.rs +++ b/src/circuit/gadget/ecc/chip/add_incomplete.rs @@ -1,6 +1,6 @@ use std::{array, collections::HashSet}; -use super::{copy, CellValue, NonIdentityEccPoint, Var}; +use super::{copy, NonIdentityEccPoint}; use ff::Field; use group::Curve; use halo2::{ @@ -149,8 +149,8 @@ impl Config { )?; let result = NonIdentityEccPoint { - x: CellValue::::new(x_r_var, x_r), - y: CellValue::::new(y_r_var, y_r), + x: x_r_var, + y: y_r_var, }; Ok(result) diff --git a/src/circuit/gadget/ecc/chip/mul.rs b/src/circuit/gadget/ecc/chip/mul.rs index fc99adfe..f0cebf11 100644 --- a/src/circuit/gadget/ecc/chip/mul.rs +++ b/src/circuit/gadget/ecc/chip/mul.rs @@ -1,4 +1,4 @@ -use super::{add, CellValue, EccPoint, NonIdentityEccPoint, Var}; +use super::{add, CellValue, EccPoint, NonIdentityEccPoint}; use crate::{ circuit::gadget::utilities::{ bool_check, copy, lookup_range_check::LookupRangeCheckConfig, ternary, @@ -194,16 +194,12 @@ impl Config { let offset = offset + 1; // Initialize the running sum for scalar decomposition to zero - let z_init = { - let z_init_cell = region.assign_advice_from_constant( - || "z_init = 0", - self.hi_config.z, - offset, - pallas::Base::zero(), - )?; - - Z(CellValue::new(z_init_cell, Some(pallas::Base::zero()))) - }; + let z_init = Z(region.assign_advice_from_constant( + || "z_init = 0", + self.hi_config.z, + offset, + pallas::Base::zero(), + )?); // Double-and-add (incomplete addition) for the `hi` half of the scalar decomposition let (x_a, y_a, zs_incomplete_hi) = self.hi_config.double_and_add( @@ -342,7 +338,7 @@ impl Config { || z_0_val.ok_or(Error::Synthesis), )?; - Z(CellValue::new(z_0_cell, z_0_val)) + Z(z_0_cell) }; // Copy in `base_x`, `base_y` to use in the LSB gate @@ -397,8 +393,8 @@ impl Config { )?; let p = EccPoint { - x: CellValue::::new(x_cell, x), - y: CellValue::::new(y_cell, y), + x: x_cell, + y: y_cell, }; // Return the result of the final complete addition as `[scalar]B` diff --git a/src/circuit/gadget/ecc/chip/mul/complete.rs b/src/circuit/gadget/ecc/chip/mul/complete.rs index 12c1d525..ba260b0f 100644 --- a/src/circuit/gadget/ecc/chip/mul/complete.rs +++ b/src/circuit/gadget/ecc/chip/mul/complete.rs @@ -1,4 +1,4 @@ -use super::super::{add, copy, CellValue, EccPoint, Var}; +use super::super::{add, copy, EccPoint}; use super::{COMPLETE_RANGE, X, Y, Z}; use crate::circuit::gadget::utilities::{bool_check, ternary}; @@ -146,7 +146,7 @@ impl Config { row + offset + 2, || z_val.ok_or(Error::Synthesis), )?; - Z(CellValue::new(z_cell, z_val)) + Z(z_cell) }; zs.push(z.clone()); @@ -168,13 +168,12 @@ impl Config { .zip(k.as_ref()) .map(|(base_y, k)| if !k { -base_y } else { base_y }); - let y_p_cell = region.assign_advice( + region.assign_advice( || "y_p", self.add_config.y_p, row + offset, || y_p.ok_or(Error::Synthesis), - )?; - CellValue::::new(y_p_cell, y_p) + )? }; // U = P if the bit is set; U = -P is the bit is not set. diff --git a/src/circuit/gadget/ecc/chip/mul/incomplete.rs b/src/circuit/gadget/ecc/chip/mul/incomplete.rs index 17874ec2..ac16c2fa 100644 --- a/src/circuit/gadget/ecc/chip/mul/incomplete.rs +++ b/src/circuit/gadget/ecc/chip/mul/incomplete.rs @@ -1,4 +1,4 @@ -use super::super::{copy, CellValue, NonIdentityEccPoint, Var}; +use super::super::{copy, NonIdentityEccPoint}; use super::{X, Y, Z}; use crate::circuit::gadget::utilities::bool_check; use ff::Field; @@ -244,13 +244,12 @@ impl Config { let z_val = z.value().zip(k.as_ref()).map(|(z_val, k)| { pallas::Base::from_u64(2) * z_val + pallas::Base::from_u64(*k as u64) }); - let z_cell = region.assign_advice( + z = region.assign_advice( || "z", self.z, row + offset, || z_val.ok_or(Error::Synthesis), )?; - z = CellValue::new(z_cell, z_val); zs.push(Z(z.clone())); // Assign `x_p`, `y_p` @@ -318,25 +317,21 @@ impl Config { .zip(y_a) .map(|(((lambda2, x_a), x_a_new), y_a)| lambda2 * (x_a - x_a_new) - y_a); let x_a_val = x_a_new; - let x_a_cell = region.assign_advice( + x_a = region.assign_advice( || "x_a", self.x_a, row + offset + 1, || x_a_val.ok_or(Error::Synthesis), )?; - x_a = CellValue::new(x_a_cell, x_a_val); } // Witness final y_a - let y_a = { - let cell = region.assign_advice( - || "y_a", - self.lambda1, - offset + NUM_BITS, - || y_a.ok_or(Error::Synthesis), - )?; - CellValue::new(cell, y_a) - }; + let y_a = region.assign_advice( + || "y_a", + self.lambda1, + offset + NUM_BITS, + || y_a.ok_or(Error::Synthesis), + )?; Ok((X(x_a), Y(y_a), zs)) } diff --git a/src/circuit/gadget/ecc/chip/mul/overflow.rs b/src/circuit/gadget/ecc/chip/mul/overflow.rs index 0f5f480a..8f78e6ee 100644 --- a/src/circuit/gadget/ecc/chip/mul/overflow.rs +++ b/src/circuit/gadget/ecc/chip/mul/overflow.rs @@ -1,4 +1,4 @@ -use super::super::{copy, CellValue, Var}; +use super::super::{copy, CellValue}; use super::Z; use crate::{ circuit::gadget::utilities::lookup_range_check::LookupRangeCheckConfig, constants::T_Q, @@ -116,13 +116,12 @@ impl Config { layouter.assign_region( || "s = alpha + k_254 â‹… 2^130", |mut region| { - let s_cell = region.assign_advice( + region.assign_advice( || "s = alpha + k_254 â‹… 2^130", self.advices[0], 0, || s_val.ok_or(Error::Synthesis), - )?; - Ok(CellValue::new(s_cell, s_val)) + ) }, )? }; diff --git a/src/circuit/gadget/ecc/chip/mul_fixed.rs b/src/circuit/gadget/ecc/chip/mul_fixed.rs index 38afca53..ca8a2dc5 100644 --- a/src/circuit/gadget/ecc/chip/mul_fixed.rs +++ b/src/circuit/gadget/ecc/chip/mul_fixed.rs @@ -1,6 +1,6 @@ use super::{ add, add_incomplete, CellValue, EccBaseFieldElemFixed, EccScalarFixed, EccScalarFixedShort, - NonIdentityEccPoint, Var, + NonIdentityEccPoint, }; use crate::circuit::gadget::utilities::decompose_running_sum::RunningSumConfig; use crate::constants::{ @@ -353,26 +353,24 @@ impl Config { assert!(x != pallas::Base::zero()); x }); - let x_cell = region.assign_advice( + let x = region.assign_advice( || format!("mul_b_x, window {}", w), self.x_p, offset + w, || x.ok_or(Error::Synthesis), )?; - let x = CellValue::new(x_cell, x); let y = mul_b.map(|mul_b| { let y = *mul_b.y(); assert!(y != pallas::Base::zero()); y }); - let y_cell = region.assign_advice( + let y = region.assign_advice( || format!("mul_b_y, window {}", w), self.y_p, offset + w, || y.ok_or(Error::Synthesis), )?; - let y = CellValue::new(y_cell, y); NonIdentityEccPoint { x, y } }; @@ -471,27 +469,24 @@ impl Config { assert!(x != pallas::Base::zero()); x }); - let x_cell = region.assign_advice( + let x = region.assign_advice( || format!("mul_b_x, window {}", NUM_WINDOWS - 1), self.x_p, offset + NUM_WINDOWS - 1, || x.ok_or(Error::Synthesis), )?; - let x = CellValue::new(x_cell, x); - let y = mul_b.map(|mul_b| { let y = *mul_b.y(); assert!(y != pallas::Base::zero()); y }); - let y_cell = region.assign_advice( + let y = region.assign_advice( || format!("mul_b_y, window {}", NUM_WINDOWS - 1), self.y_p, offset + NUM_WINDOWS - 1, || y.ok_or(Error::Synthesis), )?; - let y = CellValue::new(y_cell, y); NonIdentityEccPoint { x, y } }; diff --git a/src/circuit/gadget/ecc/chip/mul_fixed/full_width.rs b/src/circuit/gadget/ecc/chip/mul_fixed/full_width.rs index 7e632ff0..4a5f2d27 100644 --- a/src/circuit/gadget/ecc/chip/mul_fixed/full_width.rs +++ b/src/circuit/gadget/ecc/chip/mul_fixed/full_width.rs @@ -1,7 +1,7 @@ use super::super::{EccPoint, EccScalarFixed, OrchardFixedBasesFull}; use crate::{ - circuit::gadget::utilities::{range_check, CellValue, Var}, + circuit::gadget::utilities::{range_check, CellValue}, constants::{self, util, L_ORCHARD_SCALAR, NUM_WINDOWS}, }; use arrayvec::ArrayVec; @@ -111,7 +111,7 @@ impl Config { offset + idx, || window.ok_or(Error::Synthesis), )?; - windows.push(CellValue::new(window_cell, window)); + windows.push(window_cell); } Ok(windows) diff --git a/src/circuit/gadget/ecc/chip/mul_fixed/short.rs b/src/circuit/gadget/ecc/chip/mul_fixed/short.rs index 7982d998..b630ed58 100644 --- a/src/circuit/gadget/ecc/chip/mul_fixed/short.rs +++ b/src/circuit/gadget/ecc/chip/mul_fixed/short.rs @@ -2,7 +2,7 @@ use std::{array, convert::TryInto}; use super::super::{EccPoint, EccScalarFixedShort}; use crate::{ - circuit::gadget::utilities::{bool_check, copy, CellValue, Var}, + circuit::gadget::utilities::{bool_check, copy, CellValue}, constants::{ValueCommitV, L_VALUE, NUM_WINDOWS_SHORT}, }; @@ -182,7 +182,7 @@ impl Config { Ok(EccPoint { x: magnitude_mul.x, - y: CellValue::new(y_var, y_val), + y: y_var, }) }, )?; diff --git a/src/circuit/gadget/ecc/chip/witness_point.rs b/src/circuit/gadget/ecc/chip/witness_point.rs index 923f64aa..ddae656e 100644 --- a/src/circuit/gadget/ecc/chip/witness_point.rs +++ b/src/circuit/gadget/ecc/chip/witness_point.rs @@ -1,4 +1,4 @@ -use super::{CellValue, EccPoint, NonIdentityEccPoint, Var}; +use super::{CellValue, EccPoint, NonIdentityEccPoint}; use group::prime::PrimeCurveAffine; @@ -87,10 +87,7 @@ impl Config { let y_var = region.assign_advice(|| "y", self.y, offset, || y_val.ok_or(Error::Synthesis))?; - Ok(( - CellValue::::new(x_var, x_val), - CellValue::::new(y_var, y_val), - )) + Ok((x_var, y_var)) } /// Assigns a point that can be the identity. diff --git a/src/circuit/gadget/poseidon/pow5.rs b/src/circuit/gadget/poseidon/pow5.rs index fb8a9042..27101b46 100644 --- a/src/circuit/gadget/poseidon/pow5.rs +++ b/src/circuit/gadget/poseidon/pow5.rs @@ -417,10 +417,6 @@ impl From> for StateWord { } impl Var for StateWord { - fn new(var: AssignedCell, value: Option) -> Self { - Self(var) - } - fn cell(&self) -> Cell { self.0.cell() } @@ -614,10 +610,7 @@ mod tests { use super::{PoseidonInstructions, Pow5Chip, Pow5Config, StateWord}; use crate::{ - circuit::gadget::{ - poseidon::Hash, - utilities::{CellValue, Var}, - }, + circuit::gadget::poseidon::Hash, primitives::poseidon::{self, ConstantLength, P128Pow5T3 as OrchardNullifier, Spec}, }; use std::convert::TryInto; @@ -786,13 +779,12 @@ mod tests { |mut region| { let message_word = |i: usize| { let value = self.message.map(|message_vals| message_vals[i]); - let cell = region.assign_advice( + region.assign_advice( || format!("load message_{}", i), config.state[i], 0, || value.ok_or(Error::Synthesis), - )?; - Ok(CellValue::new(cell, value)) + ) }; let message: Result, Error> = (0..L).map(message_word).collect(); diff --git a/src/circuit/gadget/sinsemilla/chip.rs b/src/circuit/gadget/sinsemilla/chip.rs index d9984820..37353da6 100644 --- a/src/circuit/gadget/sinsemilla/chip.rs +++ b/src/circuit/gadget/sinsemilla/chip.rs @@ -5,7 +5,7 @@ use super::{ use crate::{ circuit::gadget::{ ecc::chip::NonIdentityEccPoint, - utilities::{lookup_range_check::LookupRangeCheckConfig, CellValue, Var}, + utilities::{lookup_range_check::LookupRangeCheckConfig, CellValue}, }, constants::OrchardFixedBasesFull, primitives::sinsemilla::{ diff --git a/src/circuit/gadget/sinsemilla/chip/hash_to_point.rs b/src/circuit/gadget/sinsemilla/chip/hash_to_point.rs index 8c8aff5b..f78996df 100644 --- a/src/circuit/gadget/sinsemilla/chip/hash_to_point.rs +++ b/src/circuit/gadget/sinsemilla/chip/hash_to_point.rs @@ -1,5 +1,5 @@ use super::super::SinsemillaInstructions; -use super::{CellValue, NonIdentityEccPoint, SinsemillaChip, Var}; +use super::{CellValue, NonIdentityEccPoint, SinsemillaChip}; use crate::primitives::sinsemilla::{self, lebs2ip_k, INV_TWO_POW_K, SINSEMILLA_S}; use halo2::{ circuit::{Chip, Region}, @@ -46,11 +46,8 @@ impl SinsemillaChip { // Constrain the initial x_q to equal the x-coordinate of the domain's `Q`. let mut x_a: X = { - let x_a = { - let cell = - region.assign_advice_from_constant(|| "fixed x_q", config.x_a, offset, x_q)?; - CellValue::new(cell, Some(x_q)) - }; + let x_a = + region.assign_advice_from_constant(|| "fixed x_q", config.x_a, offset, x_q)?; x_a.into() }; @@ -102,7 +99,7 @@ impl SinsemillaChip { )?; } - CellValue::new(y_a_cell, y_a.0) + y_a_cell }; #[cfg(test)] @@ -271,7 +268,7 @@ impl SinsemillaChip { || piece.field_elem().ok_or(Error::Synthesis), )?; region.constrain_equal(piece.cell(), cell.cell())?; - zs.push(CellValue::new(cell, piece.field_elem())); + zs.push(cell); // Assign cumulative sum such that for 0 <= i < n, // z_i = 2^K * z_{i + 1} + m_{i + 1} @@ -295,7 +292,7 @@ impl SinsemillaChip { offset + idx + 1, || z.ok_or(Error::Synthesis), )?; - zs.push(CellValue::new(cell, z)) + zs.push(cell) } zs @@ -381,7 +378,7 @@ impl SinsemillaChip { || x_a_new.ok_or(Error::Synthesis), )?; - CellValue::new(x_a_cell, x_a_new).into() + x_a_cell.into() }; // Compute y_a for the next row. diff --git a/src/circuit/gadget/sinsemilla/message.rs b/src/circuit/gadget/sinsemilla/message.rs index 05c08fa4..7894cf29 100644 --- a/src/circuit/gadget/sinsemilla/message.rs +++ b/src/circuit/gadget/sinsemilla/message.rs @@ -1,5 +1,5 @@ //! Gadget and chips for the Sinsemilla hash function. -use crate::circuit::gadget::utilities::{CellValue, Var}; +use crate::circuit::gadget::utilities::CellValue; use ff::PrimeFieldBits; use halo2::{arithmetic::FieldExt, circuit::Cell}; use std::fmt::Debug; @@ -40,9 +40,8 @@ pub struct MessagePiece { } impl MessagePiece { - pub fn new(cell: CellValue, field_elem: Option, num_words: usize) -> Self { + pub fn new(cell_value: CellValue, field_elem: Option, num_words: usize) -> Self { assert!(num_words * K < F::NUM_BITS as usize); - let cell_value = CellValue::new(cell, field_elem); Self { cell_value, num_words, diff --git a/src/circuit/gadget/sinsemilla/note_commit.rs b/src/circuit/gadget/sinsemilla/note_commit.rs index c50b9fdd..ae0cd2fc 100644 --- a/src/circuit/gadget/sinsemilla/note_commit.rs +++ b/src/circuit/gadget/sinsemilla/note_commit.rs @@ -11,7 +11,7 @@ use crate::{ chip::{EccChip, NonIdentityEccPoint}, Point, }, - utilities::{bitrange_subset, bool_check, copy, CellValue, Var}, + utilities::{bitrange_subset, bool_check, copy, CellValue}, }, constants::T_P, }; @@ -1043,15 +1043,12 @@ impl NoteCommitConfig { // Copy y. copy(&mut region, || "copy y", self.advices[5], offset, &y)?; // Witness LSB. - let lsb = { - let cell = region.assign_advice( - || "witness LSB", - self.advices[6], - offset, - || lsb.ok_or(Error::Synthesis), - )?; - CellValue::new(cell, lsb) - }; + let lsb = region.assign_advice( + || "witness LSB", + self.advices[6], + offset, + || lsb.ok_or(Error::Synthesis), + )?; // Witness k_0. copy(&mut region, || "copy k_0", self.advices[7], offset, &k_0)?; // Copy k_2. @@ -1128,15 +1125,12 @@ impl NoteCommitConfig { copy(&mut region, || "b", col_l, 0, &gate_cells.b)?; copy(&mut region, || "b_0", col_m, 0, &gate_cells.b_0)?; - let b_1 = { - let cell = region.assign_advice( - || "b_1", - col_r, - 0, - || gate_cells.b_1.ok_or(Error::Synthesis), - )?; - CellValue::new(cell, gate_cells.b_1) - }; + let b_1 = region.assign_advice( + || "b_1", + col_r, + 0, + || gate_cells.b_1.ok_or(Error::Synthesis), + )?; copy(&mut region, || "b_2", col_m, 1, &gate_cells.b_2)?; copy(&mut region, || "b_3", col_r, 1, &gate_cells.b_3)?; @@ -1155,15 +1149,12 @@ impl NoteCommitConfig { self.q_notecommit_d.enable(&mut region, 0)?; copy(&mut region, || "d", col_l, 0, &gate_cells.d)?; - let d_0 = { - let cell = region.assign_advice( - || "d_0", - col_m, - 0, - || gate_cells.d_0.ok_or(Error::Synthesis), - )?; - CellValue::new(cell, gate_cells.d_0) - }; + let d_0 = region.assign_advice( + || "d_0", + col_m, + 0, + || gate_cells.d_0.ok_or(Error::Synthesis), + )?; copy(&mut region, || "d_1", col_r, 0, &gate_cells.d_1)?; copy(&mut region, || "d_2", col_m, 1, &gate_cells.d_2)?; @@ -1199,15 +1190,12 @@ impl NoteCommitConfig { self.q_notecommit_g.enable(&mut region, 0)?; copy(&mut region, || "g", col_l, 0, &gate_cells.g)?; - let g_0 = { - let cell = region.assign_advice( - || "g_0", - col_m, - 0, - || gate_cells.g_0.ok_or(Error::Synthesis), - )?; - CellValue::new(cell, gate_cells.g_0) - }; + let g_0 = region.assign_advice( + || "g_0", + col_m, + 0, + || gate_cells.g_0.ok_or(Error::Synthesis), + )?; copy(&mut region, || "g_1", col_l, 1, &gate_cells.g_1)?; copy(&mut region, || "g_2 = z1_g", col_m, 1, &gate_cells.z1_g)?; @@ -1226,15 +1214,12 @@ impl NoteCommitConfig { copy(&mut region, || "h", col_l, 0, &gate_cells.h)?; copy(&mut region, || "h_0", col_m, 0, &gate_cells.h_0)?; - let h_1 = { - let cell = region.assign_advice( - || "h_1", - col_r, - 0, - || gate_cells.h_1.ok_or(Error::Synthesis), - )?; - CellValue::new(cell, gate_cells.h_1) - }; + let h_1 = region.assign_advice( + || "h_1", + col_r, + 0, + || gate_cells.h_1.ok_or(Error::Synthesis), + )?; Ok(h_1) }, diff --git a/src/circuit/gadget/utilities.rs b/src/circuit/gadget/utilities.rs index 12997ce1..1123d7a5 100644 --- a/src/circuit/gadget/utilities.rs +++ b/src/circuit/gadget/utilities.rs @@ -16,10 +16,7 @@ pub(crate) mod lookup_range_check; pub type CellValue = AssignedCell; /// Trait for a variable in the circuit. -pub trait Var: Clone + std::fmt::Debug { - /// Construct a new variable. - fn new(cell: AssignedCell, value: Option) -> Self; - +pub trait Var: Clone + std::fmt::Debug + From> { /// The cell at which this variable was allocated. fn cell(&self) -> Cell; @@ -28,10 +25,6 @@ pub trait Var: Clone + std::fmt::Debug { } impl Var for CellValue { - fn new(cell: AssignedCell, _value: Option) -> Self { - cell - } - fn cell(&self) -> Cell { self.cell() } @@ -56,13 +49,14 @@ pub trait UtilitiesInstructions { layouter.assign_region( || "load private", |mut region| { - let cell = region.assign_advice( - || "load private", - column, - 0, - || value.ok_or(Error::Synthesis), - )?; - Ok(Var::new(cell, value)) + region + .assign_advice( + || "load private", + column, + 0, + || value.ok_or(Error::Synthesis), + ) + .map(Self::Var::from) }, ) } diff --git a/src/circuit/gadget/utilities/cond_swap.rs b/src/circuit/gadget/utilities/cond_swap.rs index e979048e..f3d3f1be 100644 --- a/src/circuit/gadget/utilities/cond_swap.rs +++ b/src/circuit/gadget/utilities/cond_swap.rs @@ -1,4 +1,4 @@ -use super::{bool_check, copy, ternary, CellValue, UtilitiesInstructions, Var}; +use super::{bool_check, copy, ternary, CellValue, UtilitiesInstructions}; use halo2::{ circuit::{Chip, Layouter}, plonk::{Advice, Column, ConstraintSystem, Error, Selector}, @@ -76,15 +76,12 @@ impl CondSwapInstructions for CondSwapChip { let a = copy(&mut region, || "copy a", config.a, 0, &pair.0)?; // Witness `b` value - let b = { - let cell = region.assign_advice( - || "witness b", - config.b, - 0, - || pair.1.ok_or(Error::Synthesis), - )?; - CellValue::new(cell, pair.1) - }; + let b = region.assign_advice( + || "witness b", + config.b, + 0, + || pair.1.ok_or(Error::Synthesis), + )?; // Witness `swap` value let swap_val = swap.map(|swap| F::from_u64(swap as u64)); diff --git a/src/circuit/gadget/utilities/decompose_running_sum.rs b/src/circuit/gadget/utilities/decompose_running_sum.rs index 6b2da383..75aa1376 100644 --- a/src/circuit/gadget/utilities/decompose_running_sum.rs +++ b/src/circuit/gadget/utilities/decompose_running_sum.rs @@ -29,7 +29,7 @@ use halo2::{ poly::Rotation, }; -use super::{copy, range_check, CellValue, Var}; +use super::{copy, range_check, CellValue}; use crate::constants::util::decompose_word; use pasta_curves::arithmetic::FieldExt; use std::marker::PhantomData; @@ -105,15 +105,12 @@ impl word_num_bits: usize, num_windows: usize, ) -> Result, Error> { - let z_0 = { - let cell = region.assign_advice( - || "z_0 = alpha", - self.z, - offset, - || alpha.ok_or(Error::Synthesis), - )?; - CellValue::new(cell, alpha) - }; + let z_0 = region.assign_advice( + || "z_0 = alpha", + self.z, + offset, + || alpha.ok_or(Error::Synthesis), + )?; self.decompose(region, offset, z_0, strict, word_num_bits, num_windows) } @@ -194,13 +191,12 @@ impl .value() .zip(word) .map(|(z_cur_val, word)| (*z_cur_val - word) * two_pow_k_inv); - let cell = region.assign_advice( + region.assign_advice( || format!("z_{:?}", i + 1), self.z, offset + i + 1, || z_next_val.ok_or(Error::Synthesis), - )?; - CellValue::new(cell, z_next_val) + )? }; // Update `z`. diff --git a/src/circuit/gadget/utilities/lookup_range_check.rs b/src/circuit/gadget/utilities/lookup_range_check.rs index 0f535721..14f59dcb 100644 --- a/src/circuit/gadget/utilities/lookup_range_check.rs +++ b/src/circuit/gadget/utilities/lookup_range_check.rs @@ -168,15 +168,12 @@ impl LookupRangeCheckConfig layouter.assign_region( || "Witness element", |mut region| { - let z_0 = { - let cell = region.assign_advice( - || "Witness element", - self.running_sum, - 0, - || value.ok_or(Error::Synthesis), - )?; - CellValue::new(cell, value) - }; + let z_0 = region.assign_advice( + || "Witness element", + self.running_sum, + 0, + || value.ok_or(Error::Synthesis), + )?; self.range_check(&mut region, z_0, num_words, strict) }, ) @@ -247,14 +244,12 @@ impl LookupRangeCheckConfig .map(|(z, word)| (*z - word) * inv_two_pow_k); // Assign z_next - let z_cell = region.assign_advice( + region.assign_advice( || format!("z_{:?}", idx + 1), self.running_sum, idx + 1, || z_val.ok_or(Error::Synthesis), - )?; - - CellValue::new(z_cell, z_val) + )? }; zs.push(z.clone()); } @@ -300,21 +295,18 @@ impl LookupRangeCheckConfig mut layouter: impl Layouter, element: Option, num_bits: usize, - ) -> Result, Error> { + ) -> Result, Error> { assert!(num_bits <= K); layouter.assign_region( || format!("Range check {:?} bits", num_bits), |mut region| { // Witness `element` to use in the k-bit lookup. - let element = { - let cell = region.assign_advice( - || "Witness element", - self.running_sum, - 0, - || element.ok_or(Error::Synthesis), - )?; - CellValue::new(cell, element) - }; + let element = region.assign_advice( + || "Witness element", + self.running_sum, + 0, + || element.ok_or(Error::Synthesis), + )?; self.short_range_check(&mut region, element.clone(), num_bits)?; From 65a89f099b2be9dbc4b8b13ba1b44b620c118568 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 2 Dec 2021 02:10:00 +0000 Subject: [PATCH 41/59] Replace `gadget::utilities::copy` with `AssignedCell::copy_advice` Also replaces other copy-advice implementations that weren't using `copy`. --- src/circuit.rs | 34 +-- src/circuit/gadget/ecc/chip.rs | 2 +- src/circuit/gadget/ecc/chip/add.rs | 10 +- src/circuit/gadget/ecc/chip/add_incomplete.rs | 10 +- src/circuit/gadget/ecc/chip/mul.rs | 22 +- src/circuit/gadget/ecc/chip/mul/complete.rs | 12 +- src/circuit/gadget/ecc/chip/mul/incomplete.rs | 12 +- src/circuit/gadget/ecc/chip/mul/overflow.rs | 32 +-- .../ecc/chip/mul_fixed/base_field_elem.rs | 35 +-- .../gadget/ecc/chip/mul_fixed/short.rs | 15 +- src/circuit/gadget/poseidon/pow5.rs | 67 +++-- .../gadget/sinsemilla/chip/hash_to_point.rs | 7 +- src/circuit/gadget/sinsemilla/commit_ivk.rs | 98 +++----- src/circuit/gadget/sinsemilla/merkle/chip.rs | 41 +--- src/circuit/gadget/sinsemilla/note_commit.rs | 232 ++++++++++-------- src/circuit/gadget/utilities.rs | 25 +- src/circuit/gadget/utilities/cond_swap.rs | 4 +- .../gadget/utilities/decompose_running_sum.rs | 4 +- .../gadget/utilities/lookup_range_check.rs | 5 +- 19 files changed, 285 insertions(+), 382 deletions(-) diff --git a/src/circuit.rs b/src/circuit.rs index 7d6c8b69..df53bcb4 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -50,7 +50,7 @@ use gadget::{ }, note_commit::NoteCommitConfig, }, - utilities::{copy, CellValue, UtilitiesInstructions}, + utilities::{CellValue, UtilitiesInstructions}, }; use std::convert::TryInto; @@ -501,20 +501,8 @@ impl plonk::Circuit for Circuit { |mut region| { config.q_add.enable(&mut region, 0)?; - copy( - &mut region, - || "copy hash_old", - config.advices[7], - 0, - &hash_old, - )?; - copy( - &mut region, - || "copy psi_old", - config.advices[8], - 0, - &psi_old, - )?; + hash_old.copy_advice(|| "copy hash_old", &mut region, config.advices[7], 0)?; + psi_old.copy_advice(|| "copy psi_old", &mut region, config.advices[8], 0)?; let scalar_val = hash_old .value() @@ -691,19 +679,13 @@ impl plonk::Circuit for Circuit { layouter.assign_region( || "v_old - v_new = magnitude * sign", |mut region| { - copy(&mut region, || "v_old", config.advices[0], 0, &v_old)?; - copy(&mut region, || "v_new", config.advices[1], 0, &v_new)?; + v_old.copy_advice(|| "v_old", &mut region, config.advices[0], 0)?; + v_new.copy_advice(|| "v_new", &mut region, config.advices[1], 0)?; let (magnitude, sign) = v_net.clone(); - copy( - &mut region, - || "v_net magnitude", - config.advices[2], - 0, - &magnitude, - )?; - copy(&mut region, || "v_net sign", config.advices[3], 0, &sign)?; + magnitude.copy_advice(|| "v_net magnitude", &mut region, config.advices[2], 0)?; + sign.copy_advice(|| "v_net sign", &mut region, config.advices[3], 0)?; - copy(&mut region, || "anchor", config.advices[4], 0, &anchor)?; + anchor.copy_advice(|| "anchor", &mut region, config.advices[4], 0)?; region.assign_advice_from_instance( || "pub input anchor", config.primary, diff --git a/src/circuit/gadget/ecc/chip.rs b/src/circuit/gadget/ecc/chip.rs index d50bf98a..82062240 100644 --- a/src/circuit/gadget/ecc/chip.rs +++ b/src/circuit/gadget/ecc/chip.rs @@ -1,7 +1,7 @@ use super::EccInstructions; use crate::{ circuit::gadget::utilities::{ - copy, lookup_range_check::LookupRangeCheckConfig, CellValue, UtilitiesInstructions, + lookup_range_check::LookupRangeCheckConfig, CellValue, UtilitiesInstructions, }, constants::{self, NullifierK, OrchardFixedBasesFull, ValueCommitV}, primitives::sinsemilla, diff --git a/src/circuit/gadget/ecc/chip/add.rs b/src/circuit/gadget/ecc/chip/add.rs index aec2f615..1db13c52 100644 --- a/src/circuit/gadget/ecc/chip/add.rs +++ b/src/circuit/gadget/ecc/chip/add.rs @@ -1,6 +1,6 @@ use std::array; -use super::{copy, EccPoint}; +use super::EccPoint; use ff::{BatchInvert, Field}; use halo2::{ circuit::Region, @@ -223,12 +223,12 @@ impl Config { self.q_add.enable(region, offset)?; // Copy point `p` into `x_p`, `y_p` columns - copy(region, || "x_p", self.x_p, offset, &p.x)?; - copy(region, || "y_p", self.y_p, offset, &p.y)?; + p.x.copy_advice(|| "x_p", region, self.x_p, offset)?; + p.y.copy_advice(|| "y_p", region, self.y_p, offset)?; // Copy point `q` into `x_qr`, `y_qr` columns - copy(region, || "x_q", self.x_qr, offset, &q.x)?; - copy(region, || "y_q", self.y_qr, offset, &q.y)?; + q.x.copy_advice(|| "x_q", region, self.x_qr, offset)?; + q.y.copy_advice(|| "y_q", region, self.y_qr, offset)?; let (x_p, y_p) = (p.x.value(), p.y.value()); let (x_q, y_q) = (q.x.value(), q.y.value()); diff --git a/src/circuit/gadget/ecc/chip/add_incomplete.rs b/src/circuit/gadget/ecc/chip/add_incomplete.rs index d466056d..da98461a 100644 --- a/src/circuit/gadget/ecc/chip/add_incomplete.rs +++ b/src/circuit/gadget/ecc/chip/add_incomplete.rs @@ -1,6 +1,6 @@ use std::{array, collections::HashSet}; -use super::{copy, NonIdentityEccPoint}; +use super::NonIdentityEccPoint; use ff::Field; use group::Curve; use halo2::{ @@ -111,12 +111,12 @@ impl Config { .transpose()?; // Copy point `p` into `x_p`, `y_p` columns - copy(region, || "x_p", self.x_p, offset, &p.x)?; - copy(region, || "y_p", self.y_p, offset, &p.y)?; + p.x.copy_advice(|| "x_p", region, self.x_p, offset)?; + p.y.copy_advice(|| "y_p", region, self.y_p, offset)?; // Copy point `q` into `x_qr`, `y_qr` columns - copy(region, || "x_q", self.x_qr, offset, &q.x)?; - copy(region, || "y_q", self.y_qr, offset, &q.y)?; + q.x.copy_advice(|| "x_q", region, self.x_qr, offset)?; + q.y.copy_advice(|| "y_q", region, self.y_qr, offset)?; // Compute the sum `P + Q = R` let r = { diff --git a/src/circuit/gadget/ecc/chip/mul.rs b/src/circuit/gadget/ecc/chip/mul.rs index f0cebf11..05c93a51 100644 --- a/src/circuit/gadget/ecc/chip/mul.rs +++ b/src/circuit/gadget/ecc/chip/mul.rs @@ -1,8 +1,6 @@ use super::{add, CellValue, EccPoint, NonIdentityEccPoint}; use crate::{ - circuit::gadget::utilities::{ - bool_check, copy, lookup_range_check::LookupRangeCheckConfig, ternary, - }, + circuit::gadget::utilities::{bool_check, lookup_range_check::LookupRangeCheckConfig, ternary}, constants::T_Q, primitives::sinsemilla, }; @@ -342,20 +340,10 @@ impl Config { }; // Copy in `base_x`, `base_y` to use in the LSB gate - copy( - region, - || "copy base_x", - self.add_config.x_p, - offset + 1, - &base.x(), - )?; - copy( - region, - || "copy base_y", - self.add_config.y_p, - offset + 1, - &base.y(), - )?; + base.x() + .copy_advice(|| "copy base_x", region, self.add_config.x_p, offset + 1)?; + base.y() + .copy_advice(|| "copy base_y", region, self.add_config.y_p, offset + 1)?; // If `lsb` is 0, return `Acc + (-P)`. If `lsb` is 1, simply return `Acc + 0`. let x = if let Some(lsb) = lsb { diff --git a/src/circuit/gadget/ecc/chip/mul/complete.rs b/src/circuit/gadget/ecc/chip/mul/complete.rs index ba260b0f..d8bbe625 100644 --- a/src/circuit/gadget/ecc/chip/mul/complete.rs +++ b/src/circuit/gadget/ecc/chip/mul/complete.rs @@ -1,4 +1,4 @@ -use super::super::{add, copy, EccPoint}; +use super::super::{add, EccPoint}; use super::{COMPLETE_RANGE, X, Y, Z}; use crate::circuit::gadget::utilities::{bool_check, ternary}; @@ -110,12 +110,11 @@ impl Config { // Copy running sum `z` from incomplete addition let mut z = { - let z = copy( - region, + let z = z.copy_advice( || "Copy `z` running sum from incomplete addition", + region, self.z_complete, offset, - &z, )?; Z(z) }; @@ -152,12 +151,11 @@ impl Config { // Assign `y_p` for complete addition. let y_p = { - let base_y = copy( - region, + let base_y = base.y.copy_advice( || "Copy `base.y`", + region, self.z_complete, row + offset + 1, - &base.y, )?; // If the bit is set, use `y`; if the bit is not set, use `-y` diff --git a/src/circuit/gadget/ecc/chip/mul/incomplete.rs b/src/circuit/gadget/ecc/chip/mul/incomplete.rs index ac16c2fa..766026da 100644 --- a/src/circuit/gadget/ecc/chip/mul/incomplete.rs +++ b/src/circuit/gadget/ecc/chip/mul/incomplete.rs @@ -1,4 +1,4 @@ -use super::super::{copy, NonIdentityEccPoint}; +use super::super::NonIdentityEccPoint; use super::{X, Y, Z}; use crate::circuit::gadget::utilities::bool_check; use ff::Field; @@ -223,11 +223,15 @@ impl Config { // Initialise double-and-add let (mut x_a, mut y_a, mut z) = { // Initialise the running `z` sum for the scalar bits. - let z = copy(region, || "starting z", self.z, offset, &acc.2)?; + let z = acc.2.copy_advice(|| "starting z", region, self.z, offset)?; // Initialise acc - let x_a = copy(region, || "starting x_a", self.x_a, offset + 1, &acc.0)?; - let y_a = copy(region, || "starting y_a", self.lambda1, offset, &acc.1)?; + let x_a = acc + .0 + .copy_advice(|| "starting x_a", region, self.x_a, offset + 1)?; + let y_a = acc + .1 + .copy_advice(|| "starting y_a", region, self.lambda1, offset)?; (x_a, y_a.value().cloned(), z) }; diff --git a/src/circuit/gadget/ecc/chip/mul/overflow.rs b/src/circuit/gadget/ecc/chip/mul/overflow.rs index 8f78e6ee..d007a772 100644 --- a/src/circuit/gadget/ecc/chip/mul/overflow.rs +++ b/src/circuit/gadget/ecc/chip/mul/overflow.rs @@ -1,4 +1,4 @@ -use super::super::{copy, CellValue}; +use super::super::CellValue; use super::Z; use crate::{ circuit::gadget::utilities::lookup_range_check::LookupRangeCheckConfig, constants::T_Q, @@ -140,16 +140,10 @@ impl Config { self.q_mul_overflow.enable(&mut region, offset + 1)?; // Copy `z_0` - copy(&mut region, || "copy z_0", self.advices[0], offset, &*zs[0])?; + zs[0].copy_advice(|| "copy z_0", &mut region, self.advices[0], offset)?; // Copy `z_130` - copy( - &mut region, - || "copy z_130", - self.advices[0], - offset + 1, - &*zs[130], - )?; + zs[130].copy_advice(|| "copy z_130", &mut region, self.advices[0], offset + 1)?; // Witness η = inv0(z_130), where inv0(x) = 0 if x = 0, 1/x otherwise { @@ -169,34 +163,26 @@ impl Config { } // Copy `k_254` = z_254 - copy( - &mut region, - || "copy k_254", - self.advices[1], - offset, - &*zs[254], - )?; + zs[254].copy_advice(|| "copy k_254", &mut region, self.advices[1], offset)?; // Copy original alpha - copy( - &mut region, + alpha.copy_advice( || "copy original alpha", + &mut region, self.advices[1], offset + 1, - &alpha, )?; // Copy weighted sum of the decomposition of s = alpha + k_254 â‹… 2^130. - copy( - &mut region, + s_minus_lo_130.copy_advice( || "copy s_minus_lo_130", + &mut region, self.advices[1], offset + 2, - &s_minus_lo_130, )?; // Copy witnessed s to check that it was properly derived from alpha and k_254. - copy(&mut region, || "copy s", self.advices[2], offset + 1, &s)?; + s.copy_advice(|| "copy s", &mut region, self.advices[2], offset + 1)?; Ok(()) }, diff --git a/src/circuit/gadget/ecc/chip/mul_fixed/base_field_elem.rs b/src/circuit/gadget/ecc/chip/mul_fixed/base_field_elem.rs index dc421e53..fb5de1f2 100644 --- a/src/circuit/gadget/ecc/chip/mul_fixed/base_field_elem.rs +++ b/src/circuit/gadget/ecc/chip/mul_fixed/base_field_elem.rs @@ -3,7 +3,7 @@ use super::H_BASE; use crate::{ circuit::gadget::utilities::{ - bitrange_subset, copy, lookup_range_check::LookupRangeCheckConfig, range_check, CellValue, + bitrange_subset, lookup_range_check::LookupRangeCheckConfig, range_check, CellValue, }, constants::{self, T_P}, primitives::sinsemilla, @@ -290,21 +290,14 @@ impl Config { let offset = 0; // Copy α - copy( - &mut region, - || "Copy α", - self.canon_advices[0], - offset, - &alpha, - )?; + alpha.copy_advice(|| "Copy α", &mut region, self.canon_advices[0], offset)?; // z_84_alpha = the top three bits of alpha. - copy( - &mut region, + z_84_alpha.copy_advice( || "Copy z_84_alpha", + &mut region, self.canon_advices[2], offset, - &z_84_alpha, )?; } @@ -313,12 +306,11 @@ impl Config { let offset = 1; // Copy alpha_0_prime = alpha_0 + 2^130 - t_p. // We constrain this in the custom gate to be derived correctly. - copy( - &mut region, + alpha_0_prime.copy_advice( || "Copy α_0 + 2^130 - t_p", + &mut region, self.canon_advices[0], offset, - &alpha_0_prime, )?; // Decompose α into three pieces, @@ -347,30 +339,27 @@ impl Config { { let offset = 2; // Copy z_13_alpha_0_prime - copy( - &mut region, + z_13_alpha_0_prime.copy_advice( || "Copy z_13_alpha_0_prime", + &mut region, self.canon_advices[0], offset, - &z_13_alpha_0_prime, )?; // Copy z_44_alpha - copy( - &mut region, + z_44_alpha.copy_advice( || "Copy z_44_alpha", + &mut region, self.canon_advices[1], offset, - &z_44_alpha, )?; // Copy z_43_alpha - copy( - &mut region, + z_43_alpha.copy_advice( || "Copy z_43_alpha", + &mut region, self.canon_advices[2], offset, - &z_43_alpha, )?; } diff --git a/src/circuit/gadget/ecc/chip/mul_fixed/short.rs b/src/circuit/gadget/ecc/chip/mul_fixed/short.rs index b630ed58..ad20316a 100644 --- a/src/circuit/gadget/ecc/chip/mul_fixed/short.rs +++ b/src/circuit/gadget/ecc/chip/mul_fixed/short.rs @@ -2,7 +2,7 @@ use std::{array, convert::TryInto}; use super::super::{EccPoint, EccScalarFixedShort}; use crate::{ - circuit::gadget::utilities::{bool_check, copy, CellValue}, + circuit::gadget::utilities::{bool_check, CellValue}, constants::{ValueCommitV, L_VALUE, NUM_WINDOWS_SHORT}, }; @@ -138,25 +138,18 @@ impl Config { let offset = offset + 1; // Copy sign to `window` column - let sign = copy( - &mut region, + let sign = scalar.sign.copy_advice( || "sign", + &mut region, self.super_config.window, offset, - &scalar.sign, )?; // Copy last window to `u` column. // (Although the last window is not a `u` value; we are copying it into the `u` // column because there is an available cell there.) let z_21 = scalar.running_sum[21].clone(); - copy( - &mut region, - || "last_window", - self.super_config.u, - offset, - &z_21, - )?; + z_21.copy_advice(|| "last_window", &mut region, self.super_config.u, offset)?; // Conditionally negate `y`-coordinate let y_val = if let Some(sign) = sign.value() { diff --git a/src/circuit/gadget/poseidon/pow5.rs b/src/circuit/gadget/poseidon/pow5.rs index 27101b46..de6d4aa6 100644 --- a/src/circuit/gadget/poseidon/pow5.rs +++ b/src/circuit/gadget/poseidon/pow5.rs @@ -320,15 +320,15 @@ impl, const WIDTH: usize, const RATE: usize // Load the initial state into this region. let load_state_word = |i: usize| { - let value = initial_state[i].0.value().cloned(); - let var = region.assign_advice( - || format!("load state_{}", i), - config.state[i], - 0, - || value.ok_or(Error::Synthesis), - )?; - region.constrain_equal(initial_state[i].0.cell(), var.cell())?; - Ok(StateWord(var)) + initial_state[i] + .0 + .copy_advice( + || format!("load state_{}", i), + &mut region, + config.state[i], + 0, + ) + .map(StateWord) }; let initial_state: Result, Error> = (0..WIDTH).map(load_state_word).collect(); @@ -338,28 +338,24 @@ impl, const WIDTH: usize, const RATE: usize // Load the input and padding into this region. let load_input_word = |i: usize| { - let (constraint_var, value) = match (input[i].clone(), padding_values[i]) { - (Some(word), None) => (word.0.cell(), word.0.value().cloned()), - (None, Some(padding_value)) => { - let padding_var = region.assign_fixed( - || format!("load pad_{}", i), - config.rc_b[i], - 1, - || Ok(padding_value), - )?; - (padding_var.cell(), Some(padding_value)) - } + let constraint_var = match (input[i].clone(), padding_values[i]) { + (Some(word), None) => word.0, + (None, Some(padding_value)) => region.assign_fixed( + || format!("load pad_{}", i), + config.rc_b[i], + 1, + || Ok(padding_value), + )?, _ => panic!("Input and padding don't match"), }; - let var = region.assign_advice( - || format!("load input_{}", i), - config.state[i], - 1, - || value.ok_or(Error::Synthesis), - )?; - region.constrain_equal(constraint_var, var.cell())?; - - Ok(StateWord(var)) + constraint_var + .copy_advice( + || format!("load input_{}", i), + &mut region, + config.state[i], + 1, + ) + .map(StateWord) }; let input: Result, Error> = (0..RATE).map(load_input_word).collect(); let input = input?; @@ -538,15 +534,10 @@ impl Pow5State { initial_state: &State, WIDTH>, ) -> Result { let load_state_word = |i: usize| { - let value = initial_state[i].0.value().cloned(); - let var = region.assign_advice( - || format!("load state_{}", i), - config.state[i], - 0, - || value.ok_or(Error::Synthesis), - )?; - region.constrain_equal(initial_state[i].0.cell(), var.cell())?; - Ok(StateWord(var)) + initial_state[i] + .0 + .copy_advice(|| format!("load state_{}", i), region, config.state[i], 0) + .map(StateWord) }; let state: Result, _> = (0..WIDTH).map(load_state_word).collect(); diff --git a/src/circuit/gadget/sinsemilla/chip/hash_to_point.rs b/src/circuit/gadget/sinsemilla/chip/hash_to_point.rs index f78996df..67ed9268 100644 --- a/src/circuit/gadget/sinsemilla/chip/hash_to_point.rs +++ b/src/circuit/gadget/sinsemilla/chip/hash_to_point.rs @@ -261,14 +261,13 @@ impl SinsemillaChip { let mut zs = Vec::with_capacity(piece.num_words() + 1); // Copy message and initialize running sum `z` to decompose message in-circuit - let cell = region.assign_advice( + let initial_z = piece.cell_value().copy_advice( || "z_0 (copy of message piece)", + region, config.bits, offset, - || piece.field_elem().ok_or(Error::Synthesis), )?; - region.constrain_equal(piece.cell(), cell.cell())?; - zs.push(cell); + zs.push(initial_z); // Assign cumulative sum such that for 0 <= i < n, // z_i = 2^K * z_{i + 1} + m_{i + 1} diff --git a/src/circuit/gadget/sinsemilla/commit_ivk.rs b/src/circuit/gadget/sinsemilla/commit_ivk.rs index a10f8c0c..5606966b 100644 --- a/src/circuit/gadget/sinsemilla/commit_ivk.rs +++ b/src/circuit/gadget/sinsemilla/commit_ivk.rs @@ -8,7 +8,7 @@ use pasta_curves::{arithmetic::FieldExt, pallas}; use crate::{ circuit::gadget::{ ecc::{chip::EccChip, X}, - utilities::{bitrange_subset, bool_check, copy, CellValue}, + utilities::{bitrange_subset, bool_check, CellValue}, }, constants::T_P, }; @@ -474,28 +474,24 @@ impl CommitIvkConfig { { let offset = 0; // Copy in `ak` - copy( - &mut region, - || "ak", - self.advices[0], - offset, - &gate_cells.ak, - )?; + gate_cells + .ak + .copy_advice(|| "ak", &mut region, self.advices[0], offset)?; // Copy in `a` - copy(&mut region, || "a", self.advices[1], offset, &gate_cells.a)?; + gate_cells + .a + .copy_advice(|| "a", &mut region, self.advices[1], offset)?; // Copy in `b` - copy(&mut region, || "b", self.advices[2], offset, &gate_cells.b)?; + gate_cells + .b + .copy_advice(|| "b", &mut region, self.advices[2], offset)?; // Copy in `b_0` - copy( - &mut region, - || "b_0", - self.advices[3], - offset, - &gate_cells.b_0, - )?; + gate_cells + .b_0 + .copy_advice(|| "b_0", &mut region, self.advices[3], offset)?; // Witness `b_1` region.assign_advice( @@ -506,39 +502,32 @@ impl CommitIvkConfig { )?; // Copy in `b_2` - copy( - &mut region, - || "b_2", - self.advices[5], - offset, - &gate_cells.b_2, - )?; + gate_cells + .b_2 + .copy_advice(|| "b_2", &mut region, self.advices[5], offset)?; // Copy in z13_a - copy( - &mut region, + gate_cells.z13_a.copy_advice( || "z13_a", + &mut region, self.advices[6], offset, - &gate_cells.z13_a, )?; // Copy in a_prime - copy( - &mut region, + gate_cells.a_prime.copy_advice( || "a_prime", + &mut region, self.advices[7], offset, - &gate_cells.a_prime, )?; // Copy in z13_a_prime - copy( - &mut region, + gate_cells.z13_a_prime.copy_advice( || "z13_a_prime", + &mut region, self.advices[8], offset, - &gate_cells.z13_a_prime, )?; } @@ -547,28 +536,24 @@ impl CommitIvkConfig { let offset = 1; // Copy in `nk` - copy( - &mut region, - || "nk", - self.advices[0], - offset, - &gate_cells.nk, - )?; + gate_cells + .nk + .copy_advice(|| "nk", &mut region, self.advices[0], offset)?; // Copy in `c` - copy(&mut region, || "c", self.advices[1], offset, &gate_cells.c)?; + gate_cells + .c + .copy_advice(|| "c", &mut region, self.advices[1], offset)?; // Copy in `d` - copy(&mut region, || "d", self.advices[2], offset, &gate_cells.d)?; + gate_cells + .d + .copy_advice(|| "d", &mut region, self.advices[2], offset)?; // Copy in `d_0` - copy( - &mut region, - || "d_0", - self.advices[3], - offset, - &gate_cells.d_0, - )?; + gate_cells + .d_0 + .copy_advice(|| "d_0", &mut region, self.advices[3], offset)?; // Witness `d_1` region.assign_advice( @@ -579,30 +564,27 @@ impl CommitIvkConfig { )?; // Copy in z13_c - copy( - &mut region, + gate_cells.z13_c.copy_advice( || "z13_c", + &mut region, self.advices[6], offset, - &gate_cells.z13_c, )?; // Copy in b2_c_prime - copy( - &mut region, + gate_cells.b2_c_prime.copy_advice( || "b2_c_prime", + &mut region, self.advices[7], offset, - &gate_cells.b2_c_prime, )?; // Copy in z14_b2_c_prime - copy( - &mut region, + gate_cells.z14_b2_c_prime.copy_advice( || "z14_b2_c_prime", + &mut region, self.advices[8], offset, - &gate_cells.z14_b2_c_prime, )?; } diff --git a/src/circuit/gadget/sinsemilla/merkle/chip.rs b/src/circuit/gadget/sinsemilla/merkle/chip.rs index 310a7ae2..50722d47 100644 --- a/src/circuit/gadget/sinsemilla/merkle/chip.rs +++ b/src/circuit/gadget/sinsemilla/merkle/chip.rs @@ -15,7 +15,7 @@ use crate::{ circuit::gadget::utilities::{ bitrange_subset, cond_swap::{CondSwapChip, CondSwapConfig, CondSwapInstructions}, - copy, CellValue, UtilitiesInstructions, + CellValue, UtilitiesInstructions, }, constants::{L_ORCHARD_BASE, MERKLE_DEPTH_ORCHARD}, primitives::sinsemilla, @@ -287,43 +287,28 @@ impl MerkleInstructions { } } -/// Assigns a cell at a specific offset within the given region, constraining it -/// to the same value as another cell (which may be in any region). -/// -/// Returns an error if either `column` or `copy` is not in a column that was passed to -/// [`ConstraintSystem::enable_equality`] during circuit configuration. -/// -/// [`ConstraintSystem::enable_equality`]: halo2::plonk::ConstraintSystem::enable_equality -pub fn copy( - region: &mut Region<'_, F>, - annotation: A, - column: Column, - offset: usize, - copy: &CellValue, -) -> Result, Error> -where - A: Fn() -> AR, - AR: Into, -{ - // Temporarily implement `copy()` in terms of `AssignedCell::copy_advice`. - // We will remove this in a subsequent commit. - copy.copy_advice(annotation, region, column, offset) -} - pub(crate) fn transpose_option_array( option_array: Option<[T; LEN]>, ) -> [Option; LEN] { diff --git a/src/circuit/gadget/utilities/cond_swap.rs b/src/circuit/gadget/utilities/cond_swap.rs index f3d3f1be..e372bb22 100644 --- a/src/circuit/gadget/utilities/cond_swap.rs +++ b/src/circuit/gadget/utilities/cond_swap.rs @@ -1,4 +1,4 @@ -use super::{bool_check, copy, ternary, CellValue, UtilitiesInstructions}; +use super::{bool_check, ternary, CellValue, UtilitiesInstructions}; use halo2::{ circuit::{Chip, Layouter}, plonk::{Advice, Column, ConstraintSystem, Error, Selector}, @@ -73,7 +73,7 @@ impl CondSwapInstructions for CondSwapChip { config.q_swap.enable(&mut region, 0)?; // Copy in `a` value - let a = copy(&mut region, || "copy a", config.a, 0, &pair.0)?; + let a = pair.0.copy_advice(|| "copy a", &mut region, config.a, 0)?; // Witness `b` value let b = region.assign_advice( diff --git a/src/circuit/gadget/utilities/decompose_running_sum.rs b/src/circuit/gadget/utilities/decompose_running_sum.rs index 75aa1376..e22d5adf 100644 --- a/src/circuit/gadget/utilities/decompose_running_sum.rs +++ b/src/circuit/gadget/utilities/decompose_running_sum.rs @@ -29,7 +29,7 @@ use halo2::{ poly::Rotation, }; -use super::{copy, range_check, CellValue}; +use super::{range_check, CellValue}; use crate::constants::util::decompose_word; use pasta_curves::arithmetic::FieldExt; use std::marker::PhantomData; @@ -127,7 +127,7 @@ impl word_num_bits: usize, num_windows: usize, ) -> Result, Error> { - let z_0 = copy(region, || "copy z_0 = alpha", self.z, offset, &alpha)?; + let z_0 = alpha.copy_advice(|| "copy z_0 = alpha", region, self.z, offset)?; self.decompose(region, offset, z_0, strict, word_num_bits, num_windows) } diff --git a/src/circuit/gadget/utilities/lookup_range_check.rs b/src/circuit/gadget/utilities/lookup_range_check.rs index 14f59dcb..54f9018b 100644 --- a/src/circuit/gadget/utilities/lookup_range_check.rs +++ b/src/circuit/gadget/utilities/lookup_range_check.rs @@ -151,7 +151,7 @@ impl LookupRangeCheckConfig || format!("{:?} words range check", num_words), |mut region| { // Copy `element` and initialize running sum `z_0 = element` to decompose it. - let z_0 = copy(&mut region, || "z_0", self.running_sum, 0, &element)?; + let z_0 = element.copy_advice(|| "z_0", &mut region, self.running_sum, 0)?; self.range_check(&mut region, z_0, num_words, strict) }, ) @@ -278,7 +278,8 @@ impl LookupRangeCheckConfig || format!("Range check {:?} bits", num_bits), |mut region| { // Copy `element` to use in the k-bit lookup. - let element = copy(&mut region, || "element", self.running_sum, 0, &element)?; + let element = + element.copy_advice(|| "element", &mut region, self.running_sum, 0)?; self.short_range_check(&mut region, element, num_bits) }, From bacdf67428f8535e0cfcdfde7529fa440dad6496 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 2 Dec 2021 02:51:46 +0000 Subject: [PATCH 42/59] Remove the `CellValue` type In order to make the changeover easier to review, we redefined `CellValue` to be `AssignedCell`. Now we remove that type and rename throughout the codebase. --- src/circuit.rs | 6 +- src/circuit/gadget/ecc/chip.rs | 58 +++---- src/circuit/gadget/ecc/chip/mul.rs | 20 +-- src/circuit/gadget/ecc/chip/mul/overflow.rs | 8 +- src/circuit/gadget/ecc/chip/mul_fixed.rs | 6 +- .../ecc/chip/mul_fixed/base_field_elem.rs | 5 +- .../gadget/ecc/chip/mul_fixed/full_width.rs | 9 +- .../gadget/ecc/chip/mul_fixed/short.rs | 33 ++-- src/circuit/gadget/ecc/chip/witness_point.rs | 12 +- src/circuit/gadget/poseidon.rs | 13 +- src/circuit/gadget/sinsemilla/chip.rs | 11 +- .../gadget/sinsemilla/chip/hash_to_point.rs | 25 ++-- src/circuit/gadget/sinsemilla/commit_ivk.rs | 68 +++++---- src/circuit/gadget/sinsemilla/merkle/chip.rs | 6 +- src/circuit/gadget/sinsemilla/message.rs | 12 +- src/circuit/gadget/sinsemilla/note_commit.rs | 141 ++++++++++-------- src/circuit/gadget/utilities.rs | 7 +- src/circuit/gadget/utilities/cond_swap.rs | 6 +- .../gadget/utilities/decompose_running_sum.rs | 16 +- .../gadget/utilities/lookup_range_check.rs | 16 +- 20 files changed, 269 insertions(+), 209 deletions(-) diff --git a/src/circuit.rs b/src/circuit.rs index df53bcb4..79899c10 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -2,7 +2,7 @@ use group::{Curve, GroupEncoding}; use halo2::{ - circuit::{floor_planner, Layouter}, + circuit::{floor_planner, AssignedCell, Layouter}, plonk::{self, Advice, Column, Expression, Instance as InstanceColumn, Selector}, poly::Rotation, transcript::{Blake2bRead, Blake2bWrite}, @@ -50,7 +50,7 @@ use gadget::{ }, note_commit::NoteCommitConfig, }, - utilities::{CellValue, UtilitiesInstructions}, + utilities::UtilitiesInstructions, }; use std::convert::TryInto; @@ -117,7 +117,7 @@ pub struct Circuit { } impl UtilitiesInstructions for Circuit { - type Var = CellValue; + type Var = AssignedCell; } impl plonk::Circuit for Circuit { diff --git a/src/circuit/gadget/ecc/chip.rs b/src/circuit/gadget/ecc/chip.rs index 82062240..2a89bc26 100644 --- a/src/circuit/gadget/ecc/chip.rs +++ b/src/circuit/gadget/ecc/chip.rs @@ -1,7 +1,7 @@ use super::EccInstructions; use crate::{ circuit::gadget::utilities::{ - lookup_range_check::LookupRangeCheckConfig, CellValue, UtilitiesInstructions, + lookup_range_check::LookupRangeCheckConfig, UtilitiesInstructions, }, constants::{self, NullifierK, OrchardFixedBasesFull, ValueCommitV}, primitives::sinsemilla, @@ -11,7 +11,7 @@ use arrayvec::ArrayVec; use ff::Field; use group::prime::PrimeCurveAffine; use halo2::{ - circuit::{Chip, Layouter}, + circuit::{AssignedCell, Chip, Layouter}, plonk::{Advice, Column, ConstraintSystem, Error, Fixed}, }; use pasta_curves::{arithmetic::CurveAffine, pallas}; @@ -30,9 +30,9 @@ pub(super) mod witness_point; #[derive(Clone, Debug)] pub struct EccPoint { /// x-coordinate - x: CellValue, + x: AssignedCell, /// y-coordinate - y: CellValue, + y: AssignedCell, } impl EccPoint { @@ -41,8 +41,8 @@ impl EccPoint { /// This is an internal API that we only use where we know we have a valid curve point /// (specifically inside Sinsemilla). pub(in crate::circuit::gadget) fn from_coordinates_unchecked( - x: CellValue, - y: CellValue, + x: AssignedCell, + y: AssignedCell, ) -> Self { EccPoint { x, y } } @@ -62,12 +62,12 @@ impl EccPoint { } /// The cell containing the affine short-Weierstrass x-coordinate, /// or 0 for the zero point. - pub fn x(&self) -> CellValue { + pub fn x(&self) -> AssignedCell { self.x.clone() } /// The cell containing the affine short-Weierstrass y-coordinate, /// or 0 for the zero point. - pub fn y(&self) -> CellValue { + pub fn y(&self) -> AssignedCell { self.y.clone() } @@ -82,9 +82,9 @@ impl EccPoint { #[derive(Clone, Debug)] pub struct NonIdentityEccPoint { /// x-coordinate - x: CellValue, + x: AssignedCell, /// y-coordinate - y: CellValue, + y: AssignedCell, } impl NonIdentityEccPoint { @@ -93,8 +93,8 @@ impl NonIdentityEccPoint { /// This is an internal API that we only use where we know we have a valid non-identity /// curve point (specifically inside Sinsemilla). pub(in crate::circuit::gadget) fn from_coordinates_unchecked( - x: CellValue, - y: CellValue, + x: AssignedCell, + y: AssignedCell, ) -> Self { NonIdentityEccPoint { x, y } } @@ -110,11 +110,11 @@ impl NonIdentityEccPoint { } } /// The cell containing the affine short-Weierstrass x-coordinate. - pub fn x(&self) -> CellValue { + pub fn x(&self) -> AssignedCell { self.x.clone() } /// The cell containing the affine short-Weierstrass y-coordinate. - pub fn y(&self) -> CellValue { + pub fn y(&self) -> AssignedCell { self.y.clone() } } @@ -178,7 +178,7 @@ impl Chip for EccChip { } impl UtilitiesInstructions for EccChip { - type Var = CellValue; + type Var = AssignedCell; } impl EccChip { @@ -260,7 +260,7 @@ impl EccChip { #[derive(Clone, Debug)] pub struct EccScalarFixed { value: Option, - windows: ArrayVec, { constants::NUM_WINDOWS }>, + windows: ArrayVec, { constants::NUM_WINDOWS }>, } /// A signed short scalar used for fixed-base scalar multiplication. @@ -277,9 +277,11 @@ pub struct EccScalarFixed { /// k_21 must be a single bit, i.e. 0 or 1. #[derive(Clone, Debug)] pub struct EccScalarFixedShort { - magnitude: CellValue, - sign: CellValue, - running_sum: ArrayVec, { constants::NUM_WINDOWS_SHORT + 1 }>, + magnitude: AssignedCell, + // TODO: Make V an enum Sign { Positive, Negative } + sign: AssignedCell, + running_sum: + ArrayVec, { constants::NUM_WINDOWS_SHORT + 1 }>, } /// A base field element used for fixed-base scalar multiplication. @@ -293,12 +295,12 @@ pub struct EccScalarFixedShort { /// `base_field_elem`. #[derive(Clone, Debug)] struct EccBaseFieldElemFixed { - base_field_elem: CellValue, - running_sum: ArrayVec, { constants::NUM_WINDOWS + 1 }>, + base_field_elem: AssignedCell, + running_sum: ArrayVec, { constants::NUM_WINDOWS + 1 }>, } impl EccBaseFieldElemFixed { - fn base_field_elem(&self) -> CellValue { + fn base_field_elem(&self) -> AssignedCell { self.base_field_elem.clone() } } @@ -306,10 +308,10 @@ impl EccBaseFieldElemFixed { impl EccInstructions for EccChip { type ScalarFixed = EccScalarFixed; type ScalarFixedShort = EccScalarFixedShort; - type ScalarVar = CellValue; + type ScalarVar = AssignedCell; type Point = EccPoint; type NonIdentityPoint = NonIdentityEccPoint; - type X = CellValue; + type X = AssignedCell; type FixedPoints = OrchardFixedBasesFull; type FixedPointsBaseField = NullifierK; type FixedPointsShort = ValueCommitV; @@ -419,7 +421,11 @@ impl EccInstructions for EccChip { fn mul_fixed_short( &self, layouter: &mut impl Layouter, - magnitude_sign: (CellValue, CellValue), + // TODO: Return AssignedCell + magnitude_sign: ( + AssignedCell, + AssignedCell, + ), base: &Self::FixedPointsShort, ) -> Result<(Self::Point, Self::ScalarFixedShort), Error> { let config: mul_fixed::short::Config = self.config().mul_fixed_short; @@ -433,7 +439,7 @@ impl EccInstructions for EccChip { fn mul_fixed_base_field_elem( &self, layouter: &mut impl Layouter, - base_field_elem: CellValue, + base_field_elem: AssignedCell, base: &Self::FixedPointsBaseField, ) -> Result { let config = self.config().mul_fixed_base_field; diff --git a/src/circuit/gadget/ecc/chip/mul.rs b/src/circuit/gadget/ecc/chip/mul.rs index 05c93a51..a6c98a8e 100644 --- a/src/circuit/gadget/ecc/chip/mul.rs +++ b/src/circuit/gadget/ecc/chip/mul.rs @@ -1,4 +1,4 @@ -use super::{add, CellValue, EccPoint, NonIdentityEccPoint}; +use super::{add, EccPoint, NonIdentityEccPoint}; use crate::{ circuit::gadget::utilities::{bool_check, lookup_range_check::LookupRangeCheckConfig, ternary}, constants::T_Q, @@ -13,7 +13,7 @@ use bigint::U256; use ff::PrimeField; use halo2::{ arithmetic::FieldExt, - circuit::{Layouter, Region}, + circuit::{AssignedCell, Layouter, Region}, plonk::{Advice, Column, ConstraintSystem, Error, Selector}, poly::Rotation, }; @@ -164,9 +164,9 @@ impl Config { pub(super) fn assign( &self, mut layouter: impl Layouter, - alpha: CellValue, + alpha: AssignedCell, base: &NonIdentityEccPoint, - ) -> Result<(EccPoint, CellValue), Error> { + ) -> Result<(EccPoint, AssignedCell), Error> { let (result, zs): (EccPoint, Vec>) = layouter.assign_region( || "variable-base scalar mul", |mut region| { @@ -394,9 +394,9 @@ impl Config { #[derive(Clone, Debug)] // `x`-coordinate of the accumulator. -struct X(CellValue); +struct X(AssignedCell); impl Deref for X { - type Target = CellValue; + type Target = AssignedCell; fn deref(&self) -> &Self::Target { &self.0 @@ -405,9 +405,9 @@ impl Deref for X { #[derive(Clone, Debug)] // `y`-coordinate of the accumulator. -struct Y(CellValue); +struct Y(AssignedCell); impl Deref for Y { - type Target = CellValue; + type Target = AssignedCell; fn deref(&self) -> &Self::Target { &self.0 @@ -416,9 +416,9 @@ impl Deref for Y { #[derive(Clone, Debug)] // Cumulative sum `z` used to decompose the scalar. -struct Z(CellValue); +struct Z(AssignedCell); impl Deref for Z { - type Target = CellValue; + type Target = AssignedCell; fn deref(&self) -> &Self::Target { &self.0 diff --git a/src/circuit/gadget/ecc/chip/mul/overflow.rs b/src/circuit/gadget/ecc/chip/mul/overflow.rs index d007a772..30ab00ee 100644 --- a/src/circuit/gadget/ecc/chip/mul/overflow.rs +++ b/src/circuit/gadget/ecc/chip/mul/overflow.rs @@ -1,9 +1,9 @@ -use super::super::CellValue; use super::Z; use crate::{ circuit::gadget::utilities::lookup_range_check::LookupRangeCheckConfig, constants::T_Q, primitives::sinsemilla, }; +use halo2::circuit::AssignedCell; use halo2::{ circuit::Layouter, plonk::{Advice, Column, ConstraintSystem, Error, Expression, Selector}, @@ -99,7 +99,7 @@ impl Config { pub(super) fn overflow_check( &self, mut layouter: impl Layouter, - alpha: CellValue, + alpha: AssignedCell, zs: &[Z], // [z_0, z_1, ..., z_{254}, z_{255}] ) -> Result<(), Error> { // s = alpha + k_254 â‹… 2^130 is witnessed here, and then copied into @@ -194,8 +194,8 @@ impl Config { fn s_minus_lo_130( &self, mut layouter: impl Layouter, - s: CellValue, - ) -> Result, Error> { + s: AssignedCell, + ) -> Result, Error> { // Number of k-bit words we can use in the lookup decomposition. let num_words = 130 / sinsemilla::K; assert!(num_words * sinsemilla::K == 130); diff --git a/src/circuit/gadget/ecc/chip/mul_fixed.rs b/src/circuit/gadget/ecc/chip/mul_fixed.rs index ca8a2dc5..e4f2ba28 100644 --- a/src/circuit/gadget/ecc/chip/mul_fixed.rs +++ b/src/circuit/gadget/ecc/chip/mul_fixed.rs @@ -1,5 +1,5 @@ use super::{ - add, add_incomplete, CellValue, EccBaseFieldElemFixed, EccScalarFixed, EccScalarFixedShort, + add, add_incomplete, EccBaseFieldElemFixed, EccScalarFixed, EccScalarFixedShort, NonIdentityEccPoint, }; use crate::circuit::gadget::utilities::decompose_running_sum::RunningSumConfig; @@ -10,7 +10,7 @@ use crate::constants::{ use group::Curve; use halo2::{ - circuit::Region, + circuit::{AssignedCell, Region}, plonk::{Advice, Column, ConstraintSystem, Error, Expression, Fixed, Selector, VirtualCells}, poly::Rotation, }; @@ -523,7 +523,7 @@ impl ScalarFixed { // The scalar decomposition was done in the base field. For computation // outside the circuit, we now convert them back into the scalar field. fn windows_field(&self) -> Vec> { - let running_sum_to_windows = |zs: Vec>| { + let running_sum_to_windows = |zs: Vec>| { (0..(zs.len() - 1)) .map(|idx| { let z_cur = zs[idx].value(); diff --git a/src/circuit/gadget/ecc/chip/mul_fixed/base_field_elem.rs b/src/circuit/gadget/ecc/chip/mul_fixed/base_field_elem.rs index fb5de1f2..7d9b26b4 100644 --- a/src/circuit/gadget/ecc/chip/mul_fixed/base_field_elem.rs +++ b/src/circuit/gadget/ecc/chip/mul_fixed/base_field_elem.rs @@ -3,11 +3,12 @@ use super::H_BASE; use crate::{ circuit::gadget::utilities::{ - bitrange_subset, lookup_range_check::LookupRangeCheckConfig, range_check, CellValue, + bitrange_subset, lookup_range_check::LookupRangeCheckConfig, range_check, }, constants::{self, T_P}, primitives::sinsemilla, }; +use halo2::circuit::AssignedCell; use halo2::{ circuit::Layouter, plonk::{Advice, Column, ConstraintSystem, Error, Expression, Selector}, @@ -159,7 +160,7 @@ impl Config { pub fn assign( &self, mut layouter: impl Layouter, - scalar: CellValue, + scalar: AssignedCell, base: NullifierK, ) -> Result { let (scalar, acc, mul_b) = layouter.assign_region( diff --git a/src/circuit/gadget/ecc/chip/mul_fixed/full_width.rs b/src/circuit/gadget/ecc/chip/mul_fixed/full_width.rs index 4a5f2d27..48387336 100644 --- a/src/circuit/gadget/ecc/chip/mul_fixed/full_width.rs +++ b/src/circuit/gadget/ecc/chip/mul_fixed/full_width.rs @@ -1,12 +1,12 @@ use super::super::{EccPoint, EccScalarFixed, OrchardFixedBasesFull}; use crate::{ - circuit::gadget::utilities::{range_check, CellValue}, + circuit::gadget::utilities::range_check, constants::{self, util, L_ORCHARD_SCALAR, NUM_WINDOWS}, }; use arrayvec::ArrayVec; use halo2::{ - circuit::{Layouter, Region}, + circuit::{AssignedCell, Layouter, Region}, plonk::{ConstraintSystem, Error, Selector}, poly::Rotation, }; @@ -76,7 +76,7 @@ impl Config { scalar: Option, offset: usize, region: &mut Region<'_, pallas::Base>, - ) -> Result, NUM_WINDOWS>, Error> { + ) -> Result, NUM_WINDOWS>, Error> { // Enable `q_mul_fixed_full` selector for idx in 0..NUM_WINDOWS { self.q_mul_fixed_full.enable(region, offset + idx)?; @@ -92,7 +92,8 @@ impl Config { }); // Store the scalar decomposition - let mut windows: ArrayVec, NUM_WINDOWS> = ArrayVec::new(); + let mut windows: ArrayVec, NUM_WINDOWS> = + ArrayVec::new(); let scalar_windows: Vec> = if let Some(windows) = scalar_windows { assert_eq!(windows.len(), NUM_WINDOWS); diff --git a/src/circuit/gadget/ecc/chip/mul_fixed/short.rs b/src/circuit/gadget/ecc/chip/mul_fixed/short.rs index ad20316a..1083bf96 100644 --- a/src/circuit/gadget/ecc/chip/mul_fixed/short.rs +++ b/src/circuit/gadget/ecc/chip/mul_fixed/short.rs @@ -2,12 +2,12 @@ use std::{array, convert::TryInto}; use super::super::{EccPoint, EccScalarFixedShort}; use crate::{ - circuit::gadget::utilities::{bool_check, CellValue}, + circuit::gadget::utilities::bool_check, constants::{ValueCommitV, L_VALUE, NUM_WINDOWS_SHORT}, }; use halo2::{ - circuit::{Layouter, Region}, + circuit::{AssignedCell, Layouter, Region}, plonk::{ConstraintSystem, Error, Expression, Selector}, poly::Rotation, }; @@ -74,7 +74,10 @@ impl Config { &self, region: &mut Region<'_, pallas::Base>, offset: usize, - magnitude_sign: (CellValue, CellValue), + magnitude_sign: ( + AssignedCell, + AssignedCell, + ), ) -> Result { let (magnitude, sign) = magnitude_sign; @@ -98,7 +101,10 @@ impl Config { pub fn assign( &self, mut layouter: impl Layouter, - magnitude_sign: (CellValue, CellValue), + magnitude_sign: ( + AssignedCell, + AssignedCell, + ), base: &ValueCommitV, ) -> Result<(EccPoint, EccScalarFixedShort), Error> { let (scalar, acc, mul_b) = layouter.assign_region( @@ -233,14 +239,14 @@ pub mod tests { use group::Curve; use halo2::{ arithmetic::CurveAffine, - circuit::{Chip, Layouter}, + circuit::{AssignedCell, Chip, Layouter}, plonk::{Any, Error}, }; use pasta_curves::{arithmetic::FieldExt, pallas}; use crate::circuit::gadget::{ ecc::{chip::EccChip, FixedPointShort, NonIdentityPoint, Point}, - utilities::{lookup_range_check::LookupRangeCheckConfig, CellValue, UtilitiesInstructions}, + utilities::{lookup_range_check::LookupRangeCheckConfig, UtilitiesInstructions}, }; use crate::constants::load::ValueCommitV; @@ -259,7 +265,13 @@ pub mod tests { mut layouter: impl Layouter, magnitude: pallas::Base, sign: pallas::Base, - ) -> Result<(CellValue, CellValue), Error> { + ) -> Result< + ( + AssignedCell, + AssignedCell, + ), + Error, + > { let column = chip.config().advices[0]; let magnitude = chip.load_private(layouter.namespace(|| "magnitude"), column, Some(magnitude))?; @@ -372,10 +384,7 @@ pub mod tests { #[test] fn invalid_magnitude_sign() { - use crate::circuit::gadget::{ - ecc::chip::EccConfig, - utilities::{CellValue, UtilitiesInstructions}, - }; + use crate::circuit::gadget::{ecc::chip::EccConfig, utilities::UtilitiesInstructions}; use halo2::{ circuit::{Layouter, SimpleFloorPlanner}, dev::{MockProver, VerifyFailure}, @@ -391,7 +400,7 @@ pub mod tests { } impl UtilitiesInstructions for MyCircuit { - type Var = CellValue; + type Var = AssignedCell; } impl Circuit for MyCircuit { diff --git a/src/circuit/gadget/ecc/chip/witness_point.rs b/src/circuit/gadget/ecc/chip/witness_point.rs index ddae656e..d9010934 100644 --- a/src/circuit/gadget/ecc/chip/witness_point.rs +++ b/src/circuit/gadget/ecc/chip/witness_point.rs @@ -1,9 +1,9 @@ -use super::{CellValue, EccPoint, NonIdentityEccPoint}; +use super::{EccPoint, NonIdentityEccPoint}; use group::prime::PrimeCurveAffine; use halo2::{ - circuit::Region, + circuit::{AssignedCell, Region}, plonk::{Advice, Column, ConstraintSystem, Error, Expression, Selector, VirtualCells}, poly::Rotation, }; @@ -76,7 +76,13 @@ impl Config { value: Option<(pallas::Base, pallas::Base)>, offset: usize, region: &mut Region<'_, pallas::Base>, - ) -> Result<(CellValue, CellValue), Error> { + ) -> Result< + ( + AssignedCell, + AssignedCell, + ), + Error, + > { // Assign `x` value let x_val = value.map(|value| value.0); let x_var = diff --git a/src/circuit/gadget/poseidon.rs b/src/circuit/gadget/poseidon.rs index dba40b5d..8bd109e5 100644 --- a/src/circuit/gadget/poseidon.rs +++ b/src/circuit/gadget/poseidon.rs @@ -6,14 +6,13 @@ use std::fmt; use halo2::{ arithmetic::FieldExt, - circuit::{Chip, Layouter}, + circuit::{AssignedCell, Chip, Layouter}, plonk::Error, }; mod pow5; pub use pow5::{Pow5Chip, Pow5Config, StateWord}; -use crate::circuit::gadget::utilities::CellValue; use crate::primitives::poseidon::{ConstantLength, Domain, Spec, Sponge, SpongeState, State}; /// The set of circuit instructions required to use the Poseidon permutation. @@ -21,7 +20,7 @@ pub trait PoseidonInstructions, const T: usize, Chip { /// Variable representing the word over which the Poseidon permutation operates. - type Word: Clone + fmt::Debug + From> + Into>; + type Word: Clone + fmt::Debug + From> + Into>; /// Applies the Poseidon permutation to the given state. fn permute( @@ -161,7 +160,7 @@ impl< pub fn absorb( &mut self, mut layouter: impl Layouter, - value: CellValue, + value: AssignedCell, ) -> Result<(), Error> { match self.sponge { Sponge::Absorbing(ref mut input) => { @@ -192,7 +191,7 @@ impl< } /// Squeezes an element from the sponge. - pub fn squeeze(&mut self, mut layouter: impl Layouter) -> Result, Error> { + pub fn squeeze(&mut self, mut layouter: impl Layouter) -> Result, Error> { loop { match self.sponge { Sponge::Absorbing(ref input) => { @@ -266,8 +265,8 @@ impl< pub fn hash( mut self, mut layouter: impl Layouter, - message: [CellValue; L], - ) -> Result, Error> { + message: [AssignedCell; L], + ) -> Result, Error> { for (i, value) in array::IntoIter::new(message).enumerate() { self.duplex .absorb(layouter.namespace(|| format!("absorb_{}", i)), value)?; diff --git a/src/circuit/gadget/sinsemilla/chip.rs b/src/circuit/gadget/sinsemilla/chip.rs index 37353da6..9c011b23 100644 --- a/src/circuit/gadget/sinsemilla/chip.rs +++ b/src/circuit/gadget/sinsemilla/chip.rs @@ -4,8 +4,7 @@ use super::{ }; use crate::{ circuit::gadget::{ - ecc::chip::NonIdentityEccPoint, - utilities::{lookup_range_check::LookupRangeCheckConfig, CellValue}, + ecc::chip::NonIdentityEccPoint, utilities::lookup_range_check::LookupRangeCheckConfig, }, constants::OrchardFixedBasesFull, primitives::sinsemilla::{ @@ -15,7 +14,7 @@ use crate::{ use halo2::{ arithmetic::{CurveAffine, FieldExt}, - circuit::{Chip, Layouter}, + circuit::{AssignedCell, Chip, Layouter}, plonk::{ Advice, Column, ConstraintSystem, Error, Expression, Fixed, Selector, TableColumn, VirtualCells, @@ -239,14 +238,14 @@ impl SinsemillaChip { impl SinsemillaInstructions for SinsemillaChip { - type CellValue = CellValue; + type CellValue = AssignedCell; type Message = Message; type MessagePiece = MessagePiece; type RunningSum = Vec; - type X = CellValue; + type X = AssignedCell; type NonIdentityPoint = NonIdentityEccPoint; type FixedPoints = OrchardFixedBasesFull; @@ -272,7 +271,7 @@ impl SinsemillaInstructions>::Message, - ) -> Result<(NonIdentityEccPoint, Vec>>), Error> { + ) -> Result< + ( + NonIdentityEccPoint, + Vec>>, + ), + Error, + > { let config = self.config().clone(); let mut offset = 0; @@ -52,7 +59,7 @@ impl SinsemillaChip { x_a.into() }; - let mut zs_sum: Vec>> = Vec::new(); + let mut zs_sum: Vec>> = Vec::new(); // Hash each piece in the message. for (idx, piece) in message.iter().enumerate() { @@ -180,7 +187,7 @@ impl SinsemillaChip { ( X, Y, - Vec>, + Vec>, ), Error, > { @@ -398,18 +405,18 @@ impl SinsemillaChip { } /// The x-coordinate of the accumulator in a Sinsemilla hash instance. -struct X(CellValue); +struct X(AssignedCell); -impl From> for X { - fn from(cell_value: CellValue) -> Self { +impl From> for X { + fn from(cell_value: AssignedCell) -> Self { X(cell_value) } } impl Deref for X { - type Target = CellValue; + type Target = AssignedCell; - fn deref(&self) -> &CellValue { + fn deref(&self) -> &AssignedCell { &self.0 } } diff --git a/src/circuit/gadget/sinsemilla/commit_ivk.rs b/src/circuit/gadget/sinsemilla/commit_ivk.rs index 5606966b..4cca41fe 100644 --- a/src/circuit/gadget/sinsemilla/commit_ivk.rs +++ b/src/circuit/gadget/sinsemilla/commit_ivk.rs @@ -1,5 +1,5 @@ use halo2::{ - circuit::Layouter, + circuit::{AssignedCell, Layouter}, plonk::{Advice, Column, ConstraintSystem, Error, Expression, Selector}, poly::Rotation, }; @@ -8,7 +8,7 @@ use pasta_curves::{arithmetic::FieldExt, pallas}; use crate::{ circuit::gadget::{ ecc::{chip::EccChip, X}, - utilities::{bitrange_subset, bool_check, CellValue}, + utilities::{bitrange_subset, bool_check}, }, constants::T_P, }; @@ -225,8 +225,8 @@ impl CommitIvkConfig { sinsemilla_chip: SinsemillaChip, ecc_chip: EccChip, mut layouter: impl Layouter, - ak: CellValue, - nk: CellValue, + ak: AssignedCell, + nk: AssignedCell, rivk: Option, ) -> Result, Error> { // @@ -384,8 +384,14 @@ impl CommitIvkConfig { fn ak_canonicity( &self, mut layouter: impl Layouter, - a: CellValue, - ) -> Result<(CellValue, CellValue), Error> { + a: AssignedCell, + ) -> Result< + ( + AssignedCell, + AssignedCell, + ), + Error, + > { // `ak` = `a (250 bits) || b_0 (4 bits) || b_1 (1 bit)` // - b_1 = 1 => b_0 = 0 // - b_1 = 1 => a < t_P @@ -417,9 +423,15 @@ impl CommitIvkConfig { fn nk_canonicity( &self, mut layouter: impl Layouter, - b_2: CellValue, - c: CellValue, - ) -> Result<(CellValue, CellValue), Error> { + b_2: AssignedCell, + c: AssignedCell, + ) -> Result< + ( + AssignedCell, + AssignedCell, + ), + Error, + > { // `nk` = `b_2 (5 bits) || c (240 bits) || d_0 (9 bits) || d_1 (1 bit) // - d_1 = 1 => d_0 = 0 // - d_1 = 1 => b_2 + c * 2^5 < t_P @@ -596,23 +608,23 @@ impl CommitIvkConfig { // Cells used in the canonicity gate. struct GateCells { - a: CellValue, - b: CellValue, - c: CellValue, - d: CellValue, - ak: CellValue, - nk: CellValue, - b_0: CellValue, + a: AssignedCell, + b: AssignedCell, + c: AssignedCell, + d: AssignedCell, + ak: AssignedCell, + nk: AssignedCell, + b_0: AssignedCell, b_1: Option, - b_2: CellValue, - d_0: CellValue, + b_2: AssignedCell, + d_0: AssignedCell, d_1: Option, - z13_a: CellValue, - a_prime: CellValue, - z13_a_prime: CellValue, - z13_c: CellValue, - b2_c_prime: CellValue, - z14_b2_c_prime: CellValue, + z13_a: AssignedCell, + a_prime: AssignedCell, + z13_a_prime: AssignedCell, + z13_c: AssignedCell, + b2_c_prime: AssignedCell, + z14_b2_c_prime: AssignedCell, } #[cfg(test)] @@ -622,16 +634,14 @@ mod tests { circuit::gadget::{ ecc::chip::{EccChip, EccConfig}, sinsemilla::chip::SinsemillaChip, - utilities::{ - lookup_range_check::LookupRangeCheckConfig, CellValue, UtilitiesInstructions, - }, + utilities::{lookup_range_check::LookupRangeCheckConfig, UtilitiesInstructions}, }, constants::{COMMIT_IVK_PERSONALIZATION, L_ORCHARD_BASE, T_Q}, primitives::sinsemilla::CommitDomain, }; use ff::PrimeFieldBits; use halo2::{ - circuit::{Layouter, SimpleFloorPlanner}, + circuit::{AssignedCell, Layouter, SimpleFloorPlanner}, dev::MockProver, plonk::{Circuit, ConstraintSystem, Error}, }; @@ -648,7 +658,7 @@ mod tests { } impl UtilitiesInstructions for MyCircuit { - type Var = CellValue; + type Var = AssignedCell; } impl Circuit for MyCircuit { diff --git a/src/circuit/gadget/sinsemilla/merkle/chip.rs b/src/circuit/gadget/sinsemilla/merkle/chip.rs index 50722d47..3909ed14 100644 --- a/src/circuit/gadget/sinsemilla/merkle/chip.rs +++ b/src/circuit/gadget/sinsemilla/merkle/chip.rs @@ -1,5 +1,5 @@ use halo2::{ - circuit::{Chip, Layouter}, + circuit::{AssignedCell, Chip, Layouter}, plonk::{Advice, Column, ConstraintSystem, Error, Selector}, poly::Rotation, }; @@ -15,7 +15,7 @@ use crate::{ circuit::gadget::utilities::{ bitrange_subset, cond_swap::{CondSwapChip, CondSwapConfig, CondSwapInstructions}, - CellValue, UtilitiesInstructions, + UtilitiesInstructions, }, constants::{L_ORCHARD_BASE, MERKLE_DEPTH_ORCHARD}, primitives::sinsemilla, @@ -357,7 +357,7 @@ impl MerkleInstructions for MerkleChip { - type Var = CellValue; + type Var = AssignedCell; } impl CondSwapInstructions for MerkleChip { diff --git a/src/circuit/gadget/sinsemilla/message.rs b/src/circuit/gadget/sinsemilla/message.rs index 7894cf29..2581453a 100644 --- a/src/circuit/gadget/sinsemilla/message.rs +++ b/src/circuit/gadget/sinsemilla/message.rs @@ -1,7 +1,9 @@ //! Gadget and chips for the Sinsemilla hash function. -use crate::circuit::gadget::utilities::CellValue; use ff::PrimeFieldBits; -use halo2::{arithmetic::FieldExt, circuit::Cell}; +use halo2::{ + arithmetic::FieldExt, + circuit::{AssignedCell, Cell}, +}; use std::fmt::Debug; /// A [`Message`] composed of several [`MessagePiece`]s. @@ -34,13 +36,13 @@ impl std:: /// cannot exceed the base field's `NUM_BITS`. #[derive(Clone, Debug)] pub struct MessagePiece { - cell_value: CellValue, + cell_value: AssignedCell, /// The number of K-bit words in this message piece. num_words: usize, } impl MessagePiece { - pub fn new(cell_value: CellValue, field_elem: Option, num_words: usize) -> Self { + pub fn new(cell_value: AssignedCell, num_words: usize) -> Self { assert!(num_words * K < F::NUM_BITS as usize); Self { cell_value, @@ -60,7 +62,7 @@ impl MessagePiece { self.cell_value.value().cloned() } - pub fn cell_value(&self) -> CellValue { + pub fn cell_value(&self) -> AssignedCell { self.cell_value.clone() } } diff --git a/src/circuit/gadget/sinsemilla/note_commit.rs b/src/circuit/gadget/sinsemilla/note_commit.rs index d31af723..10bcd988 100644 --- a/src/circuit/gadget/sinsemilla/note_commit.rs +++ b/src/circuit/gadget/sinsemilla/note_commit.rs @@ -1,5 +1,5 @@ use halo2::{ - circuit::Layouter, + circuit::{AssignedCell, Layouter}, plonk::{Advice, Column, ConstraintSystem, Error, Expression, Selector}, poly::Rotation, }; @@ -11,7 +11,7 @@ use crate::{ chip::{EccChip, NonIdentityEccPoint}, Point, }, - utilities::{bitrange_subset, bool_check, CellValue}, + utilities::{bitrange_subset, bool_check}, }, constants::T_P, }; @@ -525,9 +525,10 @@ impl NoteCommitConfig { ecc_chip: EccChip, g_d: &NonIdentityEccPoint, pk_d: &NonIdentityEccPoint, - value: CellValue, - rho: CellValue, - psi: CellValue, + // TODO: Set V to Orchard value type + value: AssignedCell, + rho: AssignedCell, + psi: AssignedCell, rcm: Option, ) -> Result, Error> { let (gd_x, gd_y) = (g_d.x(), g_d.y()); @@ -821,8 +822,14 @@ impl NoteCommitConfig { fn canon_bitshift_130( &self, mut layouter: impl Layouter, - a: CellValue, - ) -> Result<(CellValue, CellValue), Error> { + a: AssignedCell, + ) -> Result< + ( + AssignedCell, + AssignedCell, + ), + Error, + > { // element = `a (250 bits) || b_0 (4 bits) || b_1 (1 bit)` // - b_1 = 1 => b_0 = 0 // - b_1 = 1 => a < t_P @@ -853,9 +860,15 @@ impl NoteCommitConfig { fn pkd_x_canonicity( &self, mut layouter: impl Layouter, - b_3: CellValue, - c: CellValue, - ) -> Result<(CellValue, CellValue), Error> { + b_3: AssignedCell, + c: AssignedCell, + ) -> Result< + ( + AssignedCell, + AssignedCell, + ), + Error, + > { // `x(pk_d)` = `b_3 (4 bits) || c (250 bits) || d_0 (1 bit)` // - d_0 = 1 => b_3 + 2^4 c < t_P // - 0 ≤ b_3 + 2^4 c < 2^134 @@ -893,9 +906,15 @@ impl NoteCommitConfig { fn rho_canonicity( &self, mut layouter: impl Layouter, - e_1: CellValue, - f: CellValue, - ) -> Result<(CellValue, CellValue), Error> { + e_1: AssignedCell, + f: AssignedCell, + ) -> Result< + ( + AssignedCell, + AssignedCell, + ), + Error, + > { // `rho` = `e_1 (4 bits) || f (250 bits) || g_0 (1 bit)` // - g_0 = 1 => e_1 + 2^4 f < t_P // - 0 ≤ e_1 + 2^4 f < 2^134 @@ -932,9 +951,15 @@ impl NoteCommitConfig { fn psi_canonicity( &self, mut layouter: impl Layouter, - g_1: CellValue, - g_2: CellValue, - ) -> Result<(CellValue, CellValue), Error> { + g_1: AssignedCell, + g_2: AssignedCell, + ) -> Result< + ( + AssignedCell, + AssignedCell, + ), + Error, + > { // `psi` = `g_1 (9 bits) || g_2 (240 bits) || h_0 (5 bits) || h_1 (1 bit)` // - h_1 = 1 => (h_0 = 0) ∧ (g_1 + 2^9 g_2 < t_P) // - 0 ≤ g_1 + 2^9 g_2 < 2^130 @@ -970,9 +995,9 @@ impl NoteCommitConfig { fn y_canonicity( &self, mut layouter: impl Layouter, - y: CellValue, + y: AssignedCell, lsb: Option, - ) -> Result, Error> { + ) -> Result, Error> { // Decompose the field element // y = LSB || k_0 || k_1 || k_2 || k_3 // = (bit 0) || (bits 1..=9) || (bits 10..=249) || (bits 250..=253) || (bit 254) @@ -1400,46 +1425,46 @@ impl NoteCommitConfig { } struct GateCells { - a: CellValue, - b: CellValue, - b_0: CellValue, + a: AssignedCell, + b: AssignedCell, + b_0: AssignedCell, b_1: Option, - b_2: CellValue, - b_3: CellValue, - c: CellValue, - d: CellValue, + b_2: AssignedCell, + b_3: AssignedCell, + c: AssignedCell, + d: AssignedCell, d_0: Option, - d_1: CellValue, - d_2: CellValue, - z1_d: CellValue, - e: CellValue, - e_0: CellValue, - e_1: CellValue, - f: CellValue, - g: CellValue, + d_1: AssignedCell, + d_2: AssignedCell, + z1_d: AssignedCell, + e: AssignedCell, + e_0: AssignedCell, + e_1: AssignedCell, + f: AssignedCell, + g: AssignedCell, g_0: Option, - g_1: CellValue, - z1_g: CellValue, - h: CellValue, - h_0: CellValue, + g_1: AssignedCell, + z1_g: AssignedCell, + h: AssignedCell, + h_0: AssignedCell, h_1: Option, - gd_x: CellValue, - pkd_x: CellValue, - value: CellValue, - rho: CellValue, - psi: CellValue, - a_prime: CellValue, - b3_c_prime: CellValue, - e1_f_prime: CellValue, - g1_g2_prime: CellValue, - z13_a_prime: CellValue, - z14_b3_c_prime: CellValue, - z14_e1_f_prime: CellValue, - z13_g1_g2_prime: CellValue, - z13_a: CellValue, - z13_c: CellValue, - z13_f: CellValue, - z13_g: CellValue, + gd_x: AssignedCell, + pkd_x: AssignedCell, + value: AssignedCell, + rho: AssignedCell, + psi: AssignedCell, + a_prime: AssignedCell, + b3_c_prime: AssignedCell, + e1_f_prime: AssignedCell, + g1_g2_prime: AssignedCell, + z13_a_prime: AssignedCell, + z14_b3_c_prime: AssignedCell, + z14_e1_f_prime: AssignedCell, + z13_g1_g2_prime: AssignedCell, + z13_a: AssignedCell, + z13_c: AssignedCell, + z13_f: AssignedCell, + z13_g: AssignedCell, } #[cfg(test)] @@ -1452,9 +1477,7 @@ mod tests { NonIdentityPoint, }, sinsemilla::chip::SinsemillaChip, - utilities::{ - lookup_range_check::LookupRangeCheckConfig, CellValue, UtilitiesInstructions, - }, + utilities::{lookup_range_check::LookupRangeCheckConfig, UtilitiesInstructions}, }, constants::{L_ORCHARD_BASE, L_VALUE, NOTE_COMMITMENT_PERSONALIZATION, T_Q}, primitives::sinsemilla::CommitDomain, @@ -1463,7 +1486,7 @@ mod tests { use ff::{Field, PrimeField, PrimeFieldBits}; use group::Curve; use halo2::{ - circuit::{Layouter, SimpleFloorPlanner}, + circuit::{AssignedCell, Layouter, SimpleFloorPlanner}, dev::MockProver, plonk::{Circuit, ConstraintSystem, Error}, }; @@ -1488,7 +1511,7 @@ mod tests { } impl UtilitiesInstructions for MyCircuit { - type Var = CellValue; + type Var = AssignedCell; } impl Circuit for MyCircuit { diff --git a/src/circuit/gadget/utilities.rs b/src/circuit/gadget/utilities.rs index 064ca518..b69c6aa9 100644 --- a/src/circuit/gadget/utilities.rs +++ b/src/circuit/gadget/utilities.rs @@ -12,9 +12,6 @@ pub(crate) mod cond_swap; pub(crate) mod decompose_running_sum; pub(crate) mod lookup_range_check; -/// A variable representing a field element. -pub type CellValue = AssignedCell; - /// Trait for a variable in the circuit. pub trait Var: Clone + std::fmt::Debug + From> { /// The cell at which this variable was allocated. @@ -24,7 +21,7 @@ pub trait Var: Clone + std::fmt::Debug + From> { fn value(&self) -> Option; } -impl Var for CellValue { +impl Var for AssignedCell { fn cell(&self) -> Cell { self.cell() } @@ -135,7 +132,7 @@ mod tests { struct MyCircuit(u8); impl UtilitiesInstructions for MyCircuit { - type Var = CellValue; + type Var = AssignedCell; } #[derive(Clone)] diff --git a/src/circuit/gadget/utilities/cond_swap.rs b/src/circuit/gadget/utilities/cond_swap.rs index e372bb22..d4cf1c8f 100644 --- a/src/circuit/gadget/utilities/cond_swap.rs +++ b/src/circuit/gadget/utilities/cond_swap.rs @@ -1,6 +1,6 @@ -use super::{bool_check, ternary, CellValue, UtilitiesInstructions}; +use super::{bool_check, ternary, UtilitiesInstructions}; use halo2::{ - circuit::{Chip, Layouter}, + circuit::{AssignedCell, Chip, Layouter}, plonk::{Advice, Column, ConstraintSystem, Error, Selector}, poly::Rotation, }; @@ -53,7 +53,7 @@ pub struct CondSwapConfig { } impl UtilitiesInstructions for CondSwapChip { - type Var = CellValue; + type Var = AssignedCell; } impl CondSwapInstructions for CondSwapChip { diff --git a/src/circuit/gadget/utilities/decompose_running_sum.rs b/src/circuit/gadget/utilities/decompose_running_sum.rs index e22d5adf..1374ad54 100644 --- a/src/circuit/gadget/utilities/decompose_running_sum.rs +++ b/src/circuit/gadget/utilities/decompose_running_sum.rs @@ -24,22 +24,22 @@ use ff::PrimeFieldBits; use halo2::{ - circuit::Region, + circuit::{AssignedCell, Region}, plonk::{Advice, Column, ConstraintSystem, Error, Selector}, poly::Rotation, }; -use super::{range_check, CellValue}; +use super::range_check; use crate::constants::util::decompose_word; use pasta_curves::arithmetic::FieldExt; use std::marker::PhantomData; /// The running sum $[z_0, ..., z_W]$. If created in strict mode, $z_W = 0$. -pub struct RunningSum(Vec>); +pub struct RunningSum(Vec>); impl std::ops::Deref for RunningSum { - type Target = Vec>; + type Target = Vec>; - fn deref(&self) -> &Vec> { + fn deref(&self) -> &Vec> { &self.0 } } @@ -122,7 +122,7 @@ impl &self, region: &mut Region<'_, F>, offset: usize, - alpha: CellValue, + alpha: AssignedCell, strict: bool, word_num_bits: usize, num_windows: usize, @@ -140,7 +140,7 @@ impl &self, region: &mut Region<'_, F>, offset: usize, - z_0: CellValue, + z_0: AssignedCell, strict: bool, word_num_bits: usize, num_windows: usize, @@ -176,7 +176,7 @@ impl }; // Initialize empty vector to store running sum values [z_0, ..., z_W]. - let mut zs: Vec> = vec![z_0.clone()]; + let mut zs: Vec> = vec![z_0.clone()]; let mut z = z_0; // Assign running sum `z_{i+1}` = (z_i - k_i) / (2^K) for i = 0..=n-1. diff --git a/src/circuit/gadget/utilities/lookup_range_check.rs b/src/circuit/gadget/utilities/lookup_range_check.rs index 54f9018b..6bb478d3 100644 --- a/src/circuit/gadget/utilities/lookup_range_check.rs +++ b/src/circuit/gadget/utilities/lookup_range_check.rs @@ -3,7 +3,7 @@ use crate::spec::lebs2ip; use halo2::{ - circuit::{Layouter, Region}, + circuit::{AssignedCell, Layouter, Region}, plonk::{Advice, Column, ConstraintSystem, Error, Selector, TableColumn}, poly::Rotation, }; @@ -14,11 +14,11 @@ use ff::PrimeFieldBits; use super::*; /// The running sum $[z_0, ..., z_W]$. If created in strict mode, $z_W = 0$. -pub struct RunningSum(Vec>); +pub struct RunningSum(Vec>); impl std::ops::Deref for RunningSum { - type Target = Vec>; + type Target = Vec>; - fn deref(&self) -> &Vec> { + fn deref(&self) -> &Vec> { &self.0 } } @@ -143,7 +143,7 @@ impl LookupRangeCheckConfig pub fn copy_check( &self, mut layouter: impl Layouter, - element: CellValue, + element: AssignedCell, num_words: usize, strict: bool, ) -> Result, Error> { @@ -189,7 +189,7 @@ impl LookupRangeCheckConfig fn range_check( &self, region: &mut Region<'_, F>, - element: CellValue, + element: AssignedCell, num_words: usize, strict: bool, ) -> Result, Error> { @@ -270,7 +270,7 @@ impl LookupRangeCheckConfig pub fn copy_short_check( &self, mut layouter: impl Layouter, - element: CellValue, + element: AssignedCell, num_bits: usize, ) -> Result<(), Error> { assert!(num_bits < K); @@ -322,7 +322,7 @@ impl LookupRangeCheckConfig fn short_range_check( &self, region: &mut Region<'_, F>, - element: CellValue, + element: AssignedCell, num_bits: usize, ) -> Result<(), Error> { // Enable lookup for `element`, to constrain it to 10 bits. From a44253acc71d05463a6ad566556c426363d54bd3 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 8 Dec 2021 02:16:59 +0000 Subject: [PATCH 43/59] ecc::chip: Define a `MagnitudeSign` type alias This fixes some "complex type" clippy lints, and also will make it easier to change it to a better-typed struct later. --- src/circuit/gadget/ecc/chip.rs | 17 ++++++------ .../gadget/ecc/chip/mul_fixed/short.rs | 27 +++++++------------ 2 files changed, 18 insertions(+), 26 deletions(-) diff --git a/src/circuit/gadget/ecc/chip.rs b/src/circuit/gadget/ecc/chip.rs index 2a89bc26..c911e224 100644 --- a/src/circuit/gadget/ecc/chip.rs +++ b/src/circuit/gadget/ecc/chip.rs @@ -263,6 +263,12 @@ pub struct EccScalarFixed { windows: ArrayVec, { constants::NUM_WINDOWS }>, } +// TODO: Make V a `u64` +type MagnitudeCell = AssignedCell; +// TODO: Make V an enum Sign { Positive, Negative } +type SignCell = AssignedCell; +type MagnitudeSign = (MagnitudeCell, SignCell); + /// A signed short scalar used for fixed-base scalar multiplication. /// A short scalar must have magnitude in the range [0..2^64), with /// a sign of either 1 or -1. @@ -277,9 +283,8 @@ pub struct EccScalarFixed { /// k_21 must be a single bit, i.e. 0 or 1. #[derive(Clone, Debug)] pub struct EccScalarFixedShort { - magnitude: AssignedCell, - // TODO: Make V an enum Sign { Positive, Negative } - sign: AssignedCell, + magnitude: MagnitudeCell, + sign: SignCell, running_sum: ArrayVec, { constants::NUM_WINDOWS_SHORT + 1 }>, } @@ -421,11 +426,7 @@ impl EccInstructions for EccChip { fn mul_fixed_short( &self, layouter: &mut impl Layouter, - // TODO: Return AssignedCell - magnitude_sign: ( - AssignedCell, - AssignedCell, - ), + magnitude_sign: MagnitudeSign, base: &Self::FixedPointsShort, ) -> Result<(Self::Point, Self::ScalarFixedShort), Error> { let config: mul_fixed::short::Config = self.config().mul_fixed_short; diff --git a/src/circuit/gadget/ecc/chip/mul_fixed/short.rs b/src/circuit/gadget/ecc/chip/mul_fixed/short.rs index 1083bf96..81b5c71a 100644 --- a/src/circuit/gadget/ecc/chip/mul_fixed/short.rs +++ b/src/circuit/gadget/ecc/chip/mul_fixed/short.rs @@ -2,12 +2,12 @@ use std::{array, convert::TryInto}; use super::super::{EccPoint, EccScalarFixedShort}; use crate::{ - circuit::gadget::utilities::bool_check, + circuit::gadget::{ecc::chip::MagnitudeSign, utilities::bool_check}, constants::{ValueCommitV, L_VALUE, NUM_WINDOWS_SHORT}, }; use halo2::{ - circuit::{AssignedCell, Layouter, Region}, + circuit::{Layouter, Region}, plonk::{ConstraintSystem, Error, Expression, Selector}, poly::Rotation, }; @@ -74,10 +74,7 @@ impl Config { &self, region: &mut Region<'_, pallas::Base>, offset: usize, - magnitude_sign: ( - AssignedCell, - AssignedCell, - ), + magnitude_sign: MagnitudeSign, ) -> Result { let (magnitude, sign) = magnitude_sign; @@ -101,10 +98,7 @@ impl Config { pub fn assign( &self, mut layouter: impl Layouter, - magnitude_sign: ( - AssignedCell, - AssignedCell, - ), + magnitude_sign: MagnitudeSign, base: &ValueCommitV, ) -> Result<(EccPoint, EccScalarFixedShort), Error> { let (scalar, acc, mul_b) = layouter.assign_region( @@ -245,7 +239,10 @@ pub mod tests { use pasta_curves::{arithmetic::FieldExt, pallas}; use crate::circuit::gadget::{ - ecc::{chip::EccChip, FixedPointShort, NonIdentityPoint, Point}, + ecc::{ + chip::{EccChip, MagnitudeSign}, + FixedPointShort, NonIdentityPoint, Point, + }, utilities::{lookup_range_check::LookupRangeCheckConfig, UtilitiesInstructions}, }; use crate::constants::load::ValueCommitV; @@ -265,13 +262,7 @@ pub mod tests { mut layouter: impl Layouter, magnitude: pallas::Base, sign: pallas::Base, - ) -> Result< - ( - AssignedCell, - AssignedCell, - ), - Error, - > { + ) -> Result { let column = chip.config().advices[0]; let magnitude = chip.load_private(layouter.namespace(|| "magnitude"), column, Some(magnitude))?; From 6b84d0955ab3a736c69d4a5afa416c37605ef730 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 8 Dec 2021 04:06:00 +0000 Subject: [PATCH 44/59] Fix "complex type" clippy lints --- src/circuit/gadget/ecc/chip/witness_point.rs | 13 +++---- src/circuit/gadget/sinsemilla/note_commit.rs | 41 ++++++-------------- 2 files changed, 17 insertions(+), 37 deletions(-) diff --git a/src/circuit/gadget/ecc/chip/witness_point.rs b/src/circuit/gadget/ecc/chip/witness_point.rs index d9010934..1623529c 100644 --- a/src/circuit/gadget/ecc/chip/witness_point.rs +++ b/src/circuit/gadget/ecc/chip/witness_point.rs @@ -9,6 +9,11 @@ use halo2::{ }; use pasta_curves::{arithmetic::CurveAffine, pallas}; +type Coordinates = ( + AssignedCell, + AssignedCell, +); + #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct Config { q_point: Selector, @@ -76,13 +81,7 @@ impl Config { value: Option<(pallas::Base, pallas::Base)>, offset: usize, region: &mut Region<'_, pallas::Base>, - ) -> Result< - ( - AssignedCell, - AssignedCell, - ), - Error, - > { + ) -> Result { // Assign `x` value let x_val = value.map(|value| value.0); let x_var = diff --git a/src/circuit/gadget/sinsemilla/note_commit.rs b/src/circuit/gadget/sinsemilla/note_commit.rs index 10bcd988..fd8fd24f 100644 --- a/src/circuit/gadget/sinsemilla/note_commit.rs +++ b/src/circuit/gadget/sinsemilla/note_commit.rs @@ -21,6 +21,13 @@ use super::{ CommitDomain, Message, MessagePiece, }; +/// The values of the running sum at the start and end of the range being used for a +/// canonicity check. +type CanonicityBounds = ( + AssignedCell, + AssignedCell, +); + /* We need to hash g★_d || pk★_d || i2lebsp_{64}(v) || rho || psi, @@ -817,19 +824,12 @@ impl NoteCommitConfig { Ok(cm) } - #[allow(clippy::type_complexity)] // A canonicity check helper used in checking x(g_d), y(g_d), and y(pk_d). fn canon_bitshift_130( &self, mut layouter: impl Layouter, a: AssignedCell, - ) -> Result< - ( - AssignedCell, - AssignedCell, - ), - Error, - > { + ) -> Result { // element = `a (250 bits) || b_0 (4 bits) || b_1 (1 bit)` // - b_1 = 1 => b_0 = 0 // - b_1 = 1 => a < t_P @@ -862,13 +862,7 @@ impl NoteCommitConfig { mut layouter: impl Layouter, b_3: AssignedCell, c: AssignedCell, - ) -> Result< - ( - AssignedCell, - AssignedCell, - ), - Error, - > { + ) -> Result { // `x(pk_d)` = `b_3 (4 bits) || c (250 bits) || d_0 (1 bit)` // - d_0 = 1 => b_3 + 2^4 c < t_P // - 0 ≤ b_3 + 2^4 c < 2^134 @@ -901,20 +895,13 @@ impl NoteCommitConfig { Ok((b3_c_prime, zs[14].clone())) } - #[allow(clippy::type_complexity)] // Check canonicity of `rho` encoding fn rho_canonicity( &self, mut layouter: impl Layouter, e_1: AssignedCell, f: AssignedCell, - ) -> Result< - ( - AssignedCell, - AssignedCell, - ), - Error, - > { + ) -> Result { // `rho` = `e_1 (4 bits) || f (250 bits) || g_0 (1 bit)` // - g_0 = 1 => e_1 + 2^4 f < t_P // - 0 ≤ e_1 + 2^4 f < 2^134 @@ -953,13 +940,7 @@ impl NoteCommitConfig { mut layouter: impl Layouter, g_1: AssignedCell, g_2: AssignedCell, - ) -> Result< - ( - AssignedCell, - AssignedCell, - ), - Error, - > { + ) -> Result { // `psi` = `g_1 (9 bits) || g_2 (240 bits) || h_0 (5 bits) || h_1 (1 bit)` // - h_1 = 1 => (h_0 = 0) ∧ (g_1 + 2^9 g_2 < t_P) // - 0 ≤ g_1 + 2^9 g_2 < 2^130 From a4135dde2466e57dc592efaf5b17cb607f3dd6ce Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 9 Dec 2021 00:49:01 +0000 Subject: [PATCH 45/59] ecc::chip: Fix `print_ecc_chip` The ECC test chip performs various checks that assume the chip will only be synthesized with witnesses. This assumption is broken by the chip printer test, so we fix the assumption here. --- src/circuit/gadget/ecc.rs | 11 +++++++---- src/circuit/gadget/ecc/chip/add.rs | 4 +++- src/circuit/gadget/ecc/chip/add_incomplete.rs | 15 +++++++++------ src/circuit/gadget/ecc/chip/mul.rs | 4 +++- .../gadget/ecc/chip/mul_fixed/base_field_elem.rs | 4 +++- .../gadget/ecc/chip/mul_fixed/full_width.rs | 4 +++- src/circuit/gadget/ecc/chip/mul_fixed/short.rs | 4 +++- 7 files changed, 31 insertions(+), 15 deletions(-) diff --git a/src/circuit/gadget/ecc.rs b/src/circuit/gadget/ecc.rs index 1764e500..e8aaeefd 100644 --- a/src/circuit/gadget/ecc.rs +++ b/src/circuit/gadget/ecc.rs @@ -508,7 +508,9 @@ mod tests { use super::chip::{EccChip, EccConfig}; use crate::circuit::gadget::utilities::lookup_range_check::LookupRangeCheckConfig; - struct MyCircuit {} + struct MyCircuit { + test_errors: bool, + } #[allow(non_snake_case)] impl Circuit for MyCircuit { @@ -516,7 +518,7 @@ mod tests { type FloorPlanner = SimpleFloorPlanner; fn without_witnesses(&self) -> Self { - MyCircuit {} + MyCircuit { test_errors: false } } fn configure(meta: &mut ConstraintSystem) -> Self::Config { @@ -634,6 +636,7 @@ mod tests { q_val, &q, &p_neg, + self.test_errors, )?; } @@ -678,7 +681,7 @@ mod tests { #[test] fn ecc_chip() { let k = 13; - let circuit = MyCircuit {}; + let circuit = MyCircuit { test_errors: true }; let prover = MockProver::run(k, &circuit, vec![]).unwrap(); assert_eq!(prover.verify(), Ok(())) } @@ -692,7 +695,7 @@ mod tests { root.fill(&WHITE).unwrap(); let root = root.titled("Ecc Chip Layout", ("sans-serif", 60)).unwrap(); - let circuit = MyCircuit {}; + let circuit = MyCircuit { test_errors: false }; halo2::dev::CircuitLayout::default() .render(13, &circuit, &root) .unwrap(); diff --git a/src/circuit/gadget/ecc/chip/add.rs b/src/circuit/gadget/ecc/chip/add.rs index 1db13c52..8bb6a490 100644 --- a/src/circuit/gadget/ecc/chip/add.rs +++ b/src/circuit/gadget/ecc/chip/add.rs @@ -414,7 +414,9 @@ pub mod tests { // Check complete addition P + (-P) let zero = { let result = p.add(layouter.namespace(|| "P + (-P)"), p_neg)?; - assert!(result.inner().is_identity().unwrap()); + if let Some(is_identity) = result.inner().is_identity() { + assert!(is_identity); + } result }; diff --git a/src/circuit/gadget/ecc/chip/add_incomplete.rs b/src/circuit/gadget/ecc/chip/add_incomplete.rs index da98461a..470563d6 100644 --- a/src/circuit/gadget/ecc/chip/add_incomplete.rs +++ b/src/circuit/gadget/ecc/chip/add_incomplete.rs @@ -176,6 +176,7 @@ pub mod tests { q_val: pallas::Affine, q: &NonIdentityPoint, p_neg: &NonIdentityPoint, + test_errors: bool, ) -> Result<(), Error> { // P + Q { @@ -188,13 +189,15 @@ pub mod tests { result.constrain_equal(layouter.namespace(|| "constrain P + Q"), &witnessed_result)?; } - // P + P should return an error - p.add_incomplete(layouter.namespace(|| "P + P"), p) - .expect_err("P + P should return an error"); + if test_errors { + // P + P should return an error + p.add_incomplete(layouter.namespace(|| "P + P"), p) + .expect_err("P + P should return an error"); - // P + (-P) should return an error - p.add_incomplete(layouter.namespace(|| "P + (-P)"), p_neg) - .expect_err("P + (-P) should return an error"); + // P + (-P) should return an error + p.add_incomplete(layouter.namespace(|| "P + (-P)"), p_neg) + .expect_err("P + (-P) should return an error"); + } Ok(()) } diff --git a/src/circuit/gadget/ecc/chip/mul.rs b/src/circuit/gadget/ecc/chip/mul.rs index a6c98a8e..3d522534 100644 --- a/src/circuit/gadget/ecc/chip/mul.rs +++ b/src/circuit/gadget/ecc/chip/mul.rs @@ -535,7 +535,9 @@ pub mod tests { chip.load_private(layouter.namespace(|| "zero"), column, Some(scalar_val))?; p.mul(layouter.namespace(|| "[0]B"), &scalar)? }; - assert!(result.inner().is_identity().unwrap()); + if let Some(is_identity) = result.inner().is_identity() { + assert!(is_identity); + } } // [-1]B (the largest possible base field element) diff --git a/src/circuit/gadget/ecc/chip/mul_fixed/base_field_elem.rs b/src/circuit/gadget/ecc/chip/mul_fixed/base_field_elem.rs index 7d9b26b4..dcf9aaf3 100644 --- a/src/circuit/gadget/ecc/chip/mul_fixed/base_field_elem.rs +++ b/src/circuit/gadget/ecc/chip/mul_fixed/base_field_elem.rs @@ -487,7 +487,9 @@ pub mod tests { chip.load_private(layouter.namespace(|| "zero"), column, Some(scalar_fixed))?; base.mul(layouter.namespace(|| "mul by zero"), scalar_fixed)? }; - assert!(result.inner().is_identity().unwrap()); + if let Some(is_identity) = result.inner().is_identity() { + assert!(is_identity); + } } // [-1]B is the largest base field element diff --git a/src/circuit/gadget/ecc/chip/mul_fixed/full_width.rs b/src/circuit/gadget/ecc/chip/mul_fixed/full_width.rs index 48387336..a800fbcc 100644 --- a/src/circuit/gadget/ecc/chip/mul_fixed/full_width.rs +++ b/src/circuit/gadget/ecc/chip/mul_fixed/full_width.rs @@ -295,7 +295,9 @@ pub mod tests { { let scalar_fixed = pallas::Scalar::zero(); let (result, _) = base.mul(layouter.namespace(|| "mul by zero"), Some(scalar_fixed))?; - assert!(result.inner().is_identity().unwrap()); + if let Some(is_identity) = result.inner().is_identity() { + assert!(is_identity); + } } // [-1]B is the largest scalar field element. diff --git a/src/circuit/gadget/ecc/chip/mul_fixed/short.rs b/src/circuit/gadget/ecc/chip/mul_fixed/short.rs index 81b5c71a..a7dc5cbb 100644 --- a/src/circuit/gadget/ecc/chip/mul_fixed/short.rs +++ b/src/circuit/gadget/ecc/chip/mul_fixed/short.rs @@ -367,7 +367,9 @@ pub mod tests { )?; value_commit_v.mul(layouter.namespace(|| *name), magnitude_sign)? }; - assert!(result.inner().is_identity().unwrap()); + if let Some(is_identity) = result.inner().is_identity() { + assert!(is_identity); + } } Ok(()) From 6f0cab5ffd5738b7f50e0645bb8f15ef9945ae58 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 7 Dec 2021 17:47:03 +0000 Subject: [PATCH 46/59] Replace `FieldExt::from_u64` with `PrimeField: From` --- src/circuit.rs | 23 ++++------- src/circuit/gadget/ecc/chip/add.rs | 6 +-- src/circuit/gadget/ecc/chip/mul.rs | 6 +-- src/circuit/gadget/ecc/chip/mul/complete.rs | 6 +-- src/circuit/gadget/ecc/chip/mul/incomplete.rs | 13 +++--- src/circuit/gadget/ecc/chip/mul_fixed.rs | 8 ++-- .../ecc/chip/mul_fixed/base_field_elem.rs | 6 +-- .../gadget/ecc/chip/mul_fixed/full_width.rs | 8 ++-- .../gadget/ecc/chip/mul_fixed/short.rs | 31 ++++++-------- src/circuit/gadget/poseidon/pow5.rs | 2 +- src/circuit/gadget/sinsemilla/chip.rs | 4 +- .../gadget/sinsemilla/chip/generator_table.rs | 4 +- .../gadget/sinsemilla/chip/hash_to_point.rs | 6 +-- src/circuit/gadget/sinsemilla/commit_ivk.rs | 16 ++++---- src/circuit/gadget/sinsemilla/merkle/chip.rs | 13 +++--- src/circuit/gadget/sinsemilla/note_commit.rs | 38 +++++++++--------- src/circuit/gadget/utilities.rs | 4 +- src/circuit/gadget/utilities/cond_swap.rs | 2 +- .../gadget/utilities/decompose_running_sum.rs | 8 ++-- .../gadget/utilities/lookup_range_check.rs | 36 ++++++++--------- src/constants.rs | 40 +++++++------------ src/constants/load.rs | 4 +- src/constants/util.rs | 4 +- src/primitives/poseidon.rs | 2 +- src/primitives/sinsemilla/constants.rs | 2 +- src/spec.rs | 4 +- src/tree.rs | 2 +- src/value.rs | 6 +-- 28 files changed, 138 insertions(+), 166 deletions(-) diff --git a/src/circuit.rs b/src/circuit.rs index 79899c10..47bf7115 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -8,10 +8,7 @@ use halo2::{ transcript::{Blake2bRead, Blake2bWrite}, }; use memuse::DynamicUsage; -use pasta_curves::{ - arithmetic::{CurveAffine, FieldExt}, - pallas, vesta, -}; +use pasta_curves::{arithmetic::CurveAffine, pallas, vesta}; use crate::{ constants::{ @@ -377,16 +374,14 @@ impl plonk::Circuit for Circuit { let v_old = self.load_private( layouter.namespace(|| "witness v_old"), config.advices[0], - self.v_old - .map(|v_old| pallas::Base::from_u64(v_old.inner())), + self.v_old.map(|v_old| pallas::Base::from(v_old.inner())), )?; // Witness v_new. let v_new = self.load_private( layouter.namespace(|| "witness v_new"), config.advices[0], - self.v_new - .map(|v_new| pallas::Base::from_u64(v_new.inner())), + self.v_new.map(|v_new| pallas::Base::from(v_new.inner())), )?; (psi_old, rho_old, cm_old, g_d_old, ak, nk, v_old, v_new) @@ -415,12 +410,8 @@ impl plonk::Circuit for Circuit { let v_net = { // v_old, v_new are guaranteed to be 64-bit values. Therefore, we can // move them into the base field. - let v_old = self - .v_old - .map(|v_old| pallas::Base::from_u64(v_old.inner())); - let v_new = self - .v_new - .map(|v_new| pallas::Base::from_u64(v_new.inner())); + let v_old = self.v_old.map(|v_old| pallas::Base::from(v_old.inner())); + let v_new = self.v_new.map(|v_new| pallas::Base::from(v_new.inner())); let magnitude_sign = v_old.zip(v_new).map(|(v_old, v_new)| { let is_negative = v_old < v_new; @@ -814,8 +805,8 @@ impl Instance { instance[RK_X] = *rk.x(); instance[RK_Y] = *rk.y(); instance[CMX] = self.cmx.inner(); - instance[ENABLE_SPEND] = vesta::Scalar::from_u64(self.enable_spend.into()); - instance[ENABLE_OUTPUT] = vesta::Scalar::from_u64(self.enable_output.into()); + instance[ENABLE_SPEND] = vesta::Scalar::from(u64::from(self.enable_spend)); + instance[ENABLE_OUTPUT] = vesta::Scalar::from(u64::from(self.enable_output)); [instance] } diff --git a/src/circuit/gadget/ecc/chip/add.rs b/src/circuit/gadget/ecc/chip/add.rs index 8bb6a490..489c10e9 100644 --- a/src/circuit/gadget/ecc/chip/add.rs +++ b/src/circuit/gadget/ecc/chip/add.rs @@ -121,8 +121,8 @@ impl Config { // Useful constants let one = Expression::Constant(pallas::Base::one()); - let two = Expression::Constant(pallas::Base::from_u64(2)); - let three = Expression::Constant(pallas::Base::from_u64(3)); + let two = Expression::Constant(pallas::Base::from(2)); + let three = Expression::Constant(pallas::Base::from(3)); // (x_q − x_p)â‹…((x_q − x_p)⋅λ − (y_q−y_p)) = 0 let poly1 = { @@ -302,7 +302,7 @@ impl Config { } else { if !y_p.is_zero_vartime() { // 3(x_p)^2 - let three_x_p_sq = pallas::Base::from_u64(3) * x_p.square(); + let three_x_p_sq = pallas::Base::from(3) * x_p.square(); // 1 / 2(y_p) let inv_two_y_p = y_p.invert().unwrap() * pallas::Base::TWO_INV; // λ = 3(x_p)^2 / 2(y_p) diff --git a/src/circuit/gadget/ecc/chip/mul.rs b/src/circuit/gadget/ecc/chip/mul.rs index 3d522534..863c8ca8 100644 --- a/src/circuit/gadget/ecc/chip/mul.rs +++ b/src/circuit/gadget/ecc/chip/mul.rs @@ -143,7 +143,7 @@ impl Config { // z_0 = 2 * z_1 + k_0 // => k_0 = z_0 - 2 * z_1 - let lsb = z_0 - z_1 * pallas::Base::from_u64(2); + let lsb = z_0 - z_1 * pallas::Base::from(2); let bool_check = bool_check(lsb.clone()); @@ -326,8 +326,8 @@ impl Config { // Assign z_0 = 2â‹…z_1 + k_0 let z_0 = { let z_0_val = z_1.value().zip(lsb).map(|(z_1, lsb)| { - let lsb = pallas::Base::from_u64(lsb as u64); - z_1 * pallas::Base::from_u64(2) + lsb + let lsb = pallas::Base::from(lsb as u64); + z_1 * pallas::Base::from(2) + lsb }); let z_0_cell = region.assign_advice( || "z_0", diff --git a/src/circuit/gadget/ecc/chip/mul/complete.rs b/src/circuit/gadget/ecc/chip/mul/complete.rs index d8bbe625..3b040b23 100644 --- a/src/circuit/gadget/ecc/chip/mul/complete.rs +++ b/src/circuit/gadget/ecc/chip/mul/complete.rs @@ -8,7 +8,7 @@ use halo2::{ poly::Rotation, }; -use pasta_curves::{arithmetic::FieldExt, pallas}; +use pasta_curves::pallas; #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub struct Config { @@ -59,7 +59,7 @@ impl Config { let z_next = meta.query_advice(self.z_complete, Rotation::next()); // k_{i} = z_{i} - 2â‹…z_{i+1} - let k = z_next - Expression::Constant(pallas::Base::from_u64(2)) * z_prev; + let k = z_next - Expression::Constant(pallas::Base::from(2)) * z_prev; // (k_i) â‹… (1 - k_i) = 0 let bool_check = bool_check(k.clone()); @@ -137,7 +137,7 @@ impl Config { z = { // z_next = z_cur * 2 + k_next let z_val = z.value().zip(k.as_ref()).map(|(z_val, k)| { - pallas::Base::from_u64(2) * z_val + pallas::Base::from_u64(*k as u64) + pallas::Base::from(2) * z_val + pallas::Base::from(*k as u64) }); let z_cell = region.assign_advice( || "z", diff --git a/src/circuit/gadget/ecc/chip/mul/incomplete.rs b/src/circuit/gadget/ecc/chip/mul/incomplete.rs index 766026da..6c3bfff8 100644 --- a/src/circuit/gadget/ecc/chip/mul/incomplete.rs +++ b/src/circuit/gadget/ecc/chip/mul/incomplete.rs @@ -103,13 +103,13 @@ impl Config { // The current bit in the scalar decomposition, k_i = z_i - 2â‹…z_{i+1}. // Recall that we assigned the cumulative variable `z_i` in descending order, // i from n down to 0. So z_{i+1} corresponds to the `z_prev` query. - let k = z_cur - z_prev * pallas::Base::from_u64(2); + let k = z_cur - z_prev * pallas::Base::from(2); // Check booleanity of decomposition. let bool_check = bool_check(k.clone()); // λ_{1,i}â‹…(x_{A,i} − x_{P,i}) − y_{A,i} + (2k_i - 1) y_{P,i} = 0 let gradient_1 = lambda1_cur * (x_a_cur.clone() - x_p_cur) - y_a_cur.clone() - + (k * pallas::Base::from_u64(2) - one) * y_p_cur; + + (k * pallas::Base::from(2) - one) * y_p_cur; // λ_{2,i}^2 − x_{A,i-1} − x_{R,i} − x_{A,i} = 0 let secant_line = lambda2_cur.clone().square() @@ -245,9 +245,10 @@ impl Config { // Incomplete addition for (row, k) in bits.iter().enumerate() { // z_{i} = 2 * z_{i+1} + k_i - let z_val = z.value().zip(k.as_ref()).map(|(z_val, k)| { - pallas::Base::from_u64(2) * z_val + pallas::Base::from_u64(*k as u64) - }); + let z_val = z + .value() + .zip(k.as_ref()) + .map(|(z_val, k)| pallas::Base::from(2) * z_val + pallas::Base::from(*k as u64)); z = region.assign_advice( || "z", self.z, @@ -301,7 +302,7 @@ impl Config { .zip(x_a.value()) .zip(x_r) .map(|(((lambda1, y_a), x_a), x_r)| { - pallas::Base::from_u64(2) * y_a * (x_a - x_r).invert().unwrap() - lambda1 + pallas::Base::from(2) * y_a * (x_a - x_r).invert().unwrap() - lambda1 }); region.assign_advice( || "lambda2", diff --git a/src/circuit/gadget/ecc/chip/mul_fixed.rs b/src/circuit/gadget/ecc/chip/mul_fixed.rs index e4f2ba28..7e185000 100644 --- a/src/circuit/gadget/ecc/chip/mul_fixed.rs +++ b/src/circuit/gadget/ecc/chip/mul_fixed.rs @@ -25,10 +25,10 @@ pub mod full_width; pub mod short; lazy_static! { - static ref TWO_SCALAR: pallas::Scalar = pallas::Scalar::from_u64(2); + static ref TWO_SCALAR: pallas::Scalar = pallas::Scalar::from(2); // H = 2^3 (3-bit window) - static ref H_SCALAR: pallas::Scalar = pallas::Scalar::from_u64(constants::H as u64); - static ref H_BASE: pallas::Base = pallas::Base::from_u64(constants::H as u64); + static ref H_SCALAR: pallas::Scalar = pallas::Scalar::from(constants::H as u64); + static ref H_BASE: pallas::Base = pallas::Base::from(constants::H as u64); } // A sum type for both full-width and short bases. This enables us to use the @@ -182,7 +182,7 @@ impl Config { // z_{i+1} = (z_i - a_i) / 2^3 // => a_i = z_i - z_{i+1} * 2^3 - let word = z_cur - z_next * pallas::Base::from_u64(constants::H as u64); + let word = z_cur - z_next * pallas::Base::from(constants::H as u64); self.coords_check(meta, q_mul_fixed_running_sum, word) }); diff --git a/src/circuit/gadget/ecc/chip/mul_fixed/base_field_elem.rs b/src/circuit/gadget/ecc/chip/mul_fixed/base_field_elem.rs index dcf9aaf3..e72de865 100644 --- a/src/circuit/gadget/ecc/chip/mul_fixed/base_field_elem.rs +++ b/src/circuit/gadget/ecc/chip/mul_fixed/base_field_elem.rs @@ -89,7 +89,7 @@ impl Config { let alpha_2_range_check = range_check(alpha_2.clone(), 1 << 1); // Check that α_1 + 2^2 α_2 = z_84_alpha let z_84_alpha_check = z_84_alpha.clone() - - (alpha_1.clone() + alpha_2.clone() * pallas::Base::from_u64(1 << 2)); + - (alpha_1.clone() + alpha_2.clone() * pallas::Base::from(1 << 2)); std::iter::empty() .chain(Some(("alpha_1_range_check", alpha_1_range_check))) @@ -455,11 +455,11 @@ pub mod tests { // (There is another *non-canonical* sequence // 5333333333333333333333333333333333333333332711161673731021062440252244051273333333333 in octal.) { - let h = pallas::Base::from_u64(constants::H as u64); + let h = pallas::Base::from(constants::H as u64); let scalar_fixed = "1333333333333333333333333333333333333333333333333333333333333333333333333333333333334" .chars() .fold(pallas::Base::zero(), |acc, c| { - acc * &h + &pallas::Base::from_u64(c.to_digit(8).unwrap().into()) + acc * &h + &pallas::Base::from(c.to_digit(8).unwrap() as u64) }); let result = { let scalar_fixed = chip.load_private( diff --git a/src/circuit/gadget/ecc/chip/mul_fixed/full_width.rs b/src/circuit/gadget/ecc/chip/mul_fixed/full_width.rs index a800fbcc..10b09146 100644 --- a/src/circuit/gadget/ecc/chip/mul_fixed/full_width.rs +++ b/src/circuit/gadget/ecc/chip/mul_fixed/full_width.rs @@ -10,7 +10,7 @@ use halo2::{ plonk::{ConstraintSystem, Error, Selector}, poly::Rotation, }; -use pasta_curves::{arithmetic::FieldExt, pallas}; +use pasta_curves::pallas; #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct Config { @@ -99,7 +99,7 @@ impl Config { assert_eq!(windows.len(), NUM_WINDOWS); windows .into_iter() - .map(|window| Some(pallas::Base::from_u64(window as u64))) + .map(|window| Some(pallas::Base::from(window as u64))) .collect() } else { vec![None; NUM_WINDOWS] @@ -272,11 +272,11 @@ pub mod tests { // (There is another *non-canonical* sequence // 5333333333333333333333333333333333333333332711161673731021062440252244051273333333333 in octal.) { - let h = pallas::Scalar::from_u64(constants::H as u64); + let h = pallas::Scalar::from(constants::H as u64); let scalar_fixed = "1333333333333333333333333333333333333333333333333333333333333333333333333333333333334" .chars() .fold(pallas::Scalar::zero(), |acc, c| { - acc * &h + &pallas::Scalar::from_u64(c.to_digit(8).unwrap().into()) + acc * &h + &pallas::Scalar::from(c.to_digit(8).unwrap() as u64) }); let (result, _) = base.mul(layouter.namespace(|| "mul with double"), Some(scalar_fixed))?; diff --git a/src/circuit/gadget/ecc/chip/mul_fixed/short.rs b/src/circuit/gadget/ecc/chip/mul_fixed/short.rs index a7dc5cbb..19894147 100644 --- a/src/circuit/gadget/ecc/chip/mul_fixed/short.rs +++ b/src/circuit/gadget/ecc/chip/mul_fixed/short.rs @@ -191,8 +191,7 @@ impl Config { use pasta_curves::arithmetic::FieldExt; if let (Some(magnitude), Some(sign)) = (scalar.magnitude.value(), scalar.sign.value()) { - let magnitude_is_valid = - magnitude <= &pallas::Base::from_u64(0xFFFF_FFFF_FFFF_FFFFu64); + let magnitude_is_valid = magnitude <= &pallas::Base::from(0xFFFF_FFFF_FFFF_FFFFu64); let sign_is_valid = sign * sign == pallas::Base::one(); if magnitude_is_valid && sign_is_valid { let base: super::OrchardFixedBases = base.clone().into(); @@ -287,25 +286,21 @@ pub mod tests { } let magnitude_signs = [ - ( - "random [a]B", - pallas::Base::from_u64(rand::random::()), - { - let mut random_sign = pallas::Base::one(); - if rand::random::() { - random_sign = -random_sign; - } - random_sign - }, - ), + ("random [a]B", pallas::Base::from(rand::random::()), { + let mut random_sign = pallas::Base::one(); + if rand::random::() { + random_sign = -random_sign; + } + random_sign + }), ( "[2^64 - 1]B", - pallas::Base::from_u64(0xFFFF_FFFF_FFFF_FFFFu64), + pallas::Base::from(0xFFFF_FFFF_FFFF_FFFFu64), pallas::Base::one(), ), ( "-[2^64 - 1]B", - pallas::Base::from_u64(0xFFFF_FFFF_FFFF_FFFFu64), + pallas::Base::from(0xFFFF_FFFF_FFFF_FFFFu64), -pallas::Base::one(), ), // There is a single canonical sequence of window values for which a doubling occurs on the last step: @@ -313,12 +308,12 @@ pub mod tests { // [0xB6DB_6DB6_DB6D_B6DC] B ( "mul_with_double", - pallas::Base::from_u64(0xB6DB_6DB6_DB6D_B6DCu64), + pallas::Base::from(0xB6DB_6DB6_DB6D_B6DCu64), pallas::Base::one(), ), ( "mul_with_double negative", - pallas::Base::from_u64(0xB6DB_6DB6_DB6D_B6DCu64), + pallas::Base::from(0xB6DB_6DB6_DB6D_B6DCu64), -pallas::Base::one(), ), ]; @@ -561,7 +556,7 @@ pub mod tests { { let magnitude_u64 = rand::random::(); let circuit = MyCircuit { - magnitude: Some(pallas::Base::from_u64(magnitude_u64)), + magnitude: Some(pallas::Base::from(magnitude_u64)), sign: Some(pallas::Base::zero()), magnitude_error: None, }; diff --git a/src/circuit/gadget/poseidon/pow5.rs b/src/circuit/gadget/poseidon/pow5.rs index de6d4aa6..839809e9 100644 --- a/src/circuit/gadget/poseidon/pow5.rs +++ b/src/circuit/gadget/poseidon/pow5.rs @@ -671,7 +671,7 @@ mod tests { // For the purpose of this test, compute the real final state inline. let mut expected_final_state = (0..WIDTH) - .map(|idx| Fp::from_u64(idx as u64)) + .map(|idx| Fp::from(idx as u64)) .collect::>() .try_into() .unwrap(); diff --git a/src/circuit/gadget/sinsemilla/chip.rs b/src/circuit/gadget/sinsemilla/chip.rs index 9c011b23..c3b5267a 100644 --- a/src/circuit/gadget/sinsemilla/chip.rs +++ b/src/circuit/gadget/sinsemilla/chip.rs @@ -145,7 +145,7 @@ impl SinsemillaChip { // Set up lookup argument GeneratorTableConfig::configure(meta, config.clone()); - let two = pallas::Base::from_u64(2); + let two = pallas::Base::from(2); // Closures for expressions that are derived multiple times // x_r = lambda_1^2 - x_a - x_p @@ -210,7 +210,7 @@ impl SinsemillaChip { // - rhs = (2 * Y_A_cur + (2 - q_s3) * Y_A_next + 2 * q_s3 * y_a_final) let y_check = { // lhs = 4 * lambda_2_cur * (x_a_cur - x_a_next) - let lhs = lambda_2_cur * pallas::Base::from_u64(4) * (x_a_cur - x_a_next); + let lhs = lambda_2_cur * pallas::Base::from(4) * (x_a_cur - x_a_next); // rhs = 2 * Y_A_cur + (2 - q_s3) * Y_A_next + 2 * q_s3 * y_a_final let rhs = { diff --git a/src/circuit/gadget/sinsemilla/chip/generator_table.rs b/src/circuit/gadget/sinsemilla/chip/generator_table.rs index 5c0624ac..71039d28 100644 --- a/src/circuit/gadget/sinsemilla/chip/generator_table.rs +++ b/src/circuit/gadget/sinsemilla/chip/generator_table.rs @@ -42,7 +42,7 @@ impl GeneratorTableConfig { let word = { let z_cur = meta.query_advice(config.bits, Rotation::cur()); let z_next = meta.query_advice(config.bits, Rotation::next()); - z_cur - ((q_s2 - q_s3) * z_next * pallas::Base::from_u64(1 << sinsemilla::K)) + z_cur - ((q_s2 - q_s3) * z_next * pallas::Base::from(1 << sinsemilla::K)) }; let x_p = meta.query_advice(config.x_p, Rotation::cur()); @@ -84,7 +84,7 @@ impl GeneratorTableConfig { || "table_idx", self.table_idx, index, - || Ok(pallas::Base::from_u64(index as u64)), + || Ok(pallas::Base::from(index as u64)), )?; table.assign_cell(|| "table_x", self.table_x, index, || Ok(*x))?; table.assign_cell(|| "table_y", self.table_y, index, || Ok(*y))?; diff --git a/src/circuit/gadget/sinsemilla/chip/hash_to_point.rs b/src/circuit/gadget/sinsemilla/chip/hash_to_point.rs index 332bebe7..dcfb3522 100644 --- a/src/circuit/gadget/sinsemilla/chip/hash_to_point.rs +++ b/src/circuit/gadget/sinsemilla/chip/hash_to_point.rs @@ -224,7 +224,7 @@ impl SinsemillaChip { offset + piece.num_words() - 1, || { Ok(if final_piece { - pallas::Base::from_u64(2) + pallas::Base::from(2) } else { pallas::Base::zero() }) @@ -291,7 +291,7 @@ impl SinsemillaChip { // z_{i + 1} = (z_i - m_{i + 1}) / 2^K z = z .zip(*word) - .map(|(z, word)| (z - pallas::Base::from_u64(word as u64)) * inv_2_k); + .map(|(z, word)| (z - pallas::Base::from(word as u64)) * inv_2_k); let cell = region.assign_advice( || format!("z_{:?}", idx + 1), config.bits, @@ -356,7 +356,7 @@ impl SinsemillaChip { let lambda_2 = { let lambda_2 = x_a.value().zip(y_a.0).zip(x_r).zip(lambda_1).map( |(((x_a, y_a), x_r), lambda_1)| { - pallas::Base::from_u64(2) * y_a * (x_a - x_r).invert().unwrap() - lambda_1 + pallas::Base::from(2) * y_a * (x_a - x_r).invert().unwrap() - lambda_1 }, ); diff --git a/src/circuit/gadget/sinsemilla/commit_ivk.rs b/src/circuit/gadget/sinsemilla/commit_ivk.rs index 4cca41fe..16a8c905 100644 --- a/src/circuit/gadget/sinsemilla/commit_ivk.rs +++ b/src/circuit/gadget/sinsemilla/commit_ivk.rs @@ -67,8 +67,8 @@ impl CommitIvkConfig { let q_commit_ivk = meta.query_selector(config.q_commit_ivk); // Useful constants - let two_pow_4 = pallas::Base::from_u64(1 << 4); - let two_pow_5 = pallas::Base::from_u64(1 << 5); + let two_pow_4 = pallas::Base::from(1 << 4); + let two_pow_5 = pallas::Base::from(1 << 5); let two_pow_9 = two_pow_4 * two_pow_5; let two_pow_250 = pallas::Base::from_u128(1 << 125).square(); let two_pow_254 = two_pow_250 * two_pow_4; @@ -119,7 +119,7 @@ impl CommitIvkConfig { // Check that nk = b_2 (5 bits) || c (240 bits) || d_0 (9 bits) || d_1 (1 bit) let nk_decomposition_check = { - let two_pow_245 = pallas::Base::from_u64(1 << 49).pow(&[5, 0, 0, 0]); + let two_pow_245 = pallas::Base::from(1 << 49).pow(&[5, 0, 0, 0]); b_2.clone() + c.clone() * two_pow_5 @@ -181,7 +181,7 @@ impl CommitIvkConfig { // Check that b2_c_prime = b_2 + c * 2^5 + 2^140 - t_P. // This is checked regardless of the value of d_1. let b2_c_prime_check = { - let two_pow_5 = pallas::Base::from_u64(1 << 5); + let two_pow_5 = pallas::Base::from(1 << 5); let two_pow_140 = Expression::Constant(pallas::Base::from_u128(1 << 70).square()); let t_p = Expression::Constant(pallas::Base::from_u128(T_P)); @@ -257,8 +257,8 @@ impl CommitIvkConfig { let b_2 = nk.value().map(|value| bitrange_subset(value, 0..5)); let b = b_0.zip(b_1).zip(b_2).map(|((b_0, b_1), b_2)| { - let b1_shifted = b_1 * pallas::Base::from_u64(1 << 4); - let b2_shifted = b_2 * pallas::Base::from_u64(1 << 5); + let b1_shifted = b_1 * pallas::Base::from(1 << 4); + let b2_shifted = b_2 * pallas::Base::from(1 << 5); b_0 + b1_shifted + b2_shifted }); @@ -304,7 +304,7 @@ impl CommitIvkConfig { let d = d_0 .zip(d_1) - .map(|(d_0, d_1)| d_0 + d_1 * pallas::Base::from_u64(1 << 9)); + .map(|(d_0, d_1)| d_0 + d_1 * pallas::Base::from(1 << 9)); // Constrain d_0 to be 9 bits. let d_0 = self.sinsemilla_config.lookup_config.witness_short_check( @@ -444,7 +444,7 @@ impl CommitIvkConfig { // Decompose the low 140 bits of b2_c_prime = b_2 + c * 2^5 + 2^140 - t_P, and output // the running sum at the end of it. If b2_c_prime < 2^140, the running sum will be 0. let b2_c_prime = b_2.value().zip(c.value()).map(|(b_2, c)| { - let two_pow_5 = pallas::Base::from_u64(1 << 5); + let two_pow_5 = pallas::Base::from(1 << 5); let two_pow_140 = pallas::Base::from_u128(1u128 << 70).square(); let t_p = pallas::Base::from_u128(T_P); b_2 + c * two_pow_5 + two_pow_140 - t_p diff --git a/src/circuit/gadget/sinsemilla/merkle/chip.rs b/src/circuit/gadget/sinsemilla/merkle/chip.rs index 3909ed14..609eb75e 100644 --- a/src/circuit/gadget/sinsemilla/merkle/chip.rs +++ b/src/circuit/gadget/sinsemilla/merkle/chip.rs @@ -82,7 +82,7 @@ impl MerkleChip { let q_decompose = meta.query_selector(q_decompose); let l_whole = meta.query_advice(advices[4], Rotation::next()); - let two_pow_5 = pallas::Base::from_u64(1 << 5); + let two_pow_5 = pallas::Base::from(1 << 5); let two_pow_10 = two_pow_5.square(); // a_whole is constrained by Sinsemilla to be 250 bits. @@ -101,7 +101,7 @@ impl MerkleChip { let z1_a = meta.query_advice(advices[0], Rotation::next()); let a_1 = z1_a; // a_0 = a - (a_1 * 2^10) - let a_0 = a_whole - a_1.clone() * pallas::Base::from_u64(1 << 10); + let a_0 = a_whole - a_1.clone() * pallas::Base::from(1 << 10); let l_check = a_0 - l_whole; // b = b_0||b_1||b_2 @@ -185,12 +185,12 @@ impl MerkleInstructions(field_elem: &F, bitrange: R /// i.e. 0 ≤ word < range. pub fn range_check(word: Expression, range: usize) -> Expression { (1..range).fold(word.clone(), |acc, i| { - acc * (Expression::Constant(F::from_u64(i as u64)) - word.clone()) + acc * (Expression::Constant(F::from(i as u64)) - word.clone()) }) } @@ -176,7 +176,7 @@ mod tests { || format!("witness {}", self.0), config.advice, 0, - || Ok(pallas::Base::from_u64(self.0.into())), + || Ok(pallas::Base::from(self.0 as u64)), )?; Ok(()) diff --git a/src/circuit/gadget/utilities/cond_swap.rs b/src/circuit/gadget/utilities/cond_swap.rs index d4cf1c8f..003d9ab8 100644 --- a/src/circuit/gadget/utilities/cond_swap.rs +++ b/src/circuit/gadget/utilities/cond_swap.rs @@ -84,7 +84,7 @@ impl CondSwapInstructions for CondSwapChip { )?; // Witness `swap` value - let swap_val = swap.map(|swap| F::from_u64(swap as u64)); + let swap_val = swap.map(|swap| F::from(swap as u64)); region.assign_advice( || "swap", config.swap, diff --git a/src/circuit/gadget/utilities/decompose_running_sum.rs b/src/circuit/gadget/utilities/decompose_running_sum.rs index 1374ad54..b9bc6f8a 100644 --- a/src/circuit/gadget/utilities/decompose_running_sum.rs +++ b/src/circuit/gadget/utilities/decompose_running_sum.rs @@ -84,7 +84,7 @@ impl let z_next = meta.query_advice(config.z, Rotation::next()); // z_i = 2^{K}â‹…z_{i + 1} + k_i // => k_i = z_i - 2^{K}â‹…z_{i + 1} - let word = z_cur - z_next * F::from_u64(1 << WINDOW_NUM_BITS); + let word = z_cur - z_next * F::from(1 << WINDOW_NUM_BITS); vec![q_range_check * range_check(word, 1 << WINDOW_NUM_BITS)] }); @@ -182,11 +182,11 @@ impl // Assign running sum `z_{i+1}` = (z_i - k_i) / (2^K) for i = 0..=n-1. // Outside of this helper, z_0 = alpha must have already been loaded into the // `z` column at `offset`. - let two_pow_k_inv = F::from_u64(1 << WINDOW_NUM_BITS as u64).invert().unwrap(); + let two_pow_k_inv = F::from(1 << WINDOW_NUM_BITS as u64).invert().unwrap(); for (i, word) in words.iter().enumerate() { // z_next = (z_cur - word) / (2^K) let z_next = { - let word = word.map(|word| F::from_u64(word as u64)); + let word = word.map(|word| F::from(word as u64)); let z_next_val = z .value() .zip(word) @@ -319,7 +319,7 @@ mod tests { // Random 64-bit word { - let alpha = pallas::Base::from_u64(rand::random()); + let alpha = pallas::Base::from(rand::random::()); // Strict full decomposition should pass. let circuit: MyCircuit< diff --git a/src/circuit/gadget/utilities/lookup_range_check.rs b/src/circuit/gadget/utilities/lookup_range_check.rs index 6bb478d3..4d1ad033 100644 --- a/src/circuit/gadget/utilities/lookup_range_check.rs +++ b/src/circuit/gadget/utilities/lookup_range_check.rs @@ -76,7 +76,7 @@ impl LookupRangeCheckConfig let running_sum_lookup = { let running_sum_word = { let z_next = meta.query_advice(config.running_sum, Rotation::next()); - z_cur.clone() - z_next * F::from_u64(1 << K) + z_cur.clone() - z_next * F::from(1 << K) }; q_running.clone() * running_sum_word @@ -104,7 +104,7 @@ impl LookupRangeCheckConfig let shifted_word = meta.query_advice(config.running_sum, Rotation::cur()); let inv_two_pow_s = meta.query_advice(config.running_sum, Rotation::next()); - let two_pow_k = F::from_u64(1 << K); + let two_pow_k = F::from(1 << K); // shifted_word = word * 2^{K-s} // = word * 2^K * inv_two_pow_s @@ -128,7 +128,7 @@ impl LookupRangeCheckConfig || "table_idx", self.table_idx, index, - || Ok(F::from_u64(index as u64)), + || Ok(F::from(index as u64)), )?; } Ok(()) @@ -210,7 +210,7 @@ impl LookupRangeCheckConfig let words: Option> = bits.map(|bits| { bits.chunks_exact(K) - .map(|word| F::from_u64(lebs2ip::(&(word.try_into().unwrap())))) + .map(|word| F::from(lebs2ip::(&(word.try_into().unwrap())))) .collect::>() }); if let Some(words) = words { @@ -229,7 +229,7 @@ impl LookupRangeCheckConfig // For `element` = a_0 + 2^10 a_1 + ... + 2^{120} a_{12}}, initialize z_0 = `element`. // If `element` fits in 130 bits, we end up with z_{13} = 0. let mut z = element; - let inv_two_pow_k = F::from_u64(1u64 << K).invert().unwrap(); + let inv_two_pow_k = F::from(1u64 << K).invert().unwrap(); for (idx, word) in words.iter().enumerate() { // Enable q_lookup on this row self.q_lookup.enable(region, idx)?; @@ -336,7 +336,7 @@ impl LookupRangeCheckConfig // Assign shifted `element * 2^{K - num_bits}` let shifted = element.value().map(|element| { - let shift = F::from_u64(1 << (K - num_bits)); + let shift = F::from(1 << (K - num_bits)); *element * shift }); @@ -348,7 +348,7 @@ impl LookupRangeCheckConfig )?; // Assign 2^{-num_bits} from a fixed column. - let inv_two_pow_s = F::from_u64(1 << num_bits).invert().unwrap(); + let inv_two_pow_s = F::from(1 << num_bits).invert().unwrap(); region.assign_advice_from_constant( || format!("2^(-{})", num_bits), self.running_sum, @@ -411,12 +411,8 @@ mod tests { // Lookup constraining element to be no longer than num_words * K bits. let elements_and_expected_final_zs = [ - ( - F::from_u64((1 << (self.num_words * K)) - 1), - F::zero(), - true, - ), // a word that is within self.num_words * K bits long - (F::from_u64(1 << (self.num_words * K)), F::one(), false), // a word that is just over self.num_words * K bits long + (F::from((1 << (self.num_words * K)) - 1), F::zero(), true), // a word that is within self.num_words * K bits long + (F::from(1 << (self.num_words * K)), F::one(), false), // a word that is just over self.num_words * K bits long ]; fn expected_zs( @@ -431,7 +427,7 @@ mod tests { .take(num_words * K) .collect::>() .chunks_exact(K) - .map(|chunk| F::from_u64(lebs2ip::(chunk.try_into().unwrap()))) + .map(|chunk| F::from(lebs2ip::(chunk.try_into().unwrap()))) .collect::>() }; let expected_zs = { @@ -538,7 +534,7 @@ mod tests { // Edge case: K bits { let circuit: MyCircuit = MyCircuit { - element: Some(pallas::Base::from_u64((1 << K) - 1)), + element: Some(pallas::Base::from((1 << K) - 1)), num_bits: K, }; let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); @@ -548,7 +544,7 @@ mod tests { // Element within `num_bits` { let circuit: MyCircuit = MyCircuit { - element: Some(pallas::Base::from_u64((1 << 6) - 1)), + element: Some(pallas::Base::from((1 << 6) - 1)), num_bits: 6, }; let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); @@ -558,7 +554,7 @@ mod tests { // Element larger than `num_bits` but within K bits { let circuit: MyCircuit = MyCircuit { - element: Some(pallas::Base::from_u64(1 << 6)), + element: Some(pallas::Base::from(1 << 6)), num_bits: 6, }; let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); @@ -574,7 +570,7 @@ mod tests { // Element larger than K bits { let circuit: MyCircuit = MyCircuit { - element: Some(pallas::Base::from_u64(1 << K)), + element: Some(pallas::Base::from(1 << K)), num_bits: 6, }; let prover = MockProver::::run(11, &circuit, vec![]).unwrap(); @@ -597,11 +593,11 @@ mod tests { // num_bits { let num_bits = 6; - let shifted = pallas::Base::from_u64((1 << num_bits) - 1); + let shifted = pallas::Base::from((1 << num_bits) - 1); // Recall that shifted = element * 2^{K-s} // => element = shifted * 2^{s-K} let element = shifted - * pallas::Base::from_u64(1 << (K as u64 - num_bits)) + * pallas::Base::from(1 << (K as u64 - num_bits)) .invert() .unwrap(); let circuit: MyCircuit = MyCircuit { diff --git a/src/constants.rs b/src/constants.rs index c95c27e8..c417a078 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -100,8 +100,8 @@ fn compute_window_table(base: C, num_windows: usize) -> Vec<[C; (0..H) .map(|k| { // scalar = (k+2)*(8^w) - let scalar = C::ScalarExt::from_u64(k as u64 + 2) - * C::ScalarExt::from_u64(H as u64).pow(&[w as u64, 0, 0, 0]); + let scalar = C::Scalar::from(k as u64 + 2) + * C::Scalar::from(H as u64).pow(&[w as u64, 0, 0, 0]); (base * scalar).to_affine() }) .collect::>() @@ -114,19 +114,14 @@ fn compute_window_table(base: C, num_windows: usize) -> Vec<[C; // For the last window, we compute [k * (2^3)^w - sum]B, where sum is defined // as sum = \sum_{j = 0}^{`num_windows - 2`} 2^{3j+1} let sum = (0..(num_windows - 1)).fold(C::ScalarExt::zero(), |acc, j| { - acc + C::ScalarExt::from_u64(2).pow(&[ - FIXED_BASE_WINDOW_SIZE as u64 * j as u64 + 1, - 0, - 0, - 0, - ]) + acc + C::Scalar::from(2).pow(&[FIXED_BASE_WINDOW_SIZE as u64 * j as u64 + 1, 0, 0, 0]) }); window_table.push( (0..H) .map(|k| { // scalar = k * (2^3)^w - sum, where w = `num_windows - 1` - let scalar = C::ScalarExt::from_u64(k as u64) - * C::ScalarExt::from_u64(H as u64).pow(&[(num_windows - 1) as u64, 0, 0, 0]) + let scalar = C::Scalar::from(k as u64) + * C::Scalar::from(H as u64).pow(&[(num_windows - 1) as u64, 0, 0, 0]) - sum; (base * scalar).to_affine() }) @@ -142,7 +137,7 @@ fn compute_window_table(base: C, num_windows: usize) -> Vec<[C; /// Here, we pre-compute and store the coefficients of the interpolation polynomial. fn compute_lagrange_coeffs(base: C, num_windows: usize) -> Vec<[C::Base; H]> { // We are interpolating over the 3-bit window, k \in [0..8) - let points: Vec<_> = (0..H).map(|i| C::Base::from_u64(i as u64)).collect(); + let points: Vec<_> = (0..H).map(|i| C::Base::from(i as u64)).collect(); let window_table = compute_window_table(base, num_windows); @@ -183,8 +178,8 @@ fn find_zs_and_us(base: C, num_windows: usize) -> Option(base: C, num_windows: usize) { // Compute the actual x-coordinate of the multiple [(k+2)*(8^w)]B. let point = base - * C::Scalar::from_u64(bits as u64 + 2) - * C::Scalar::from_u64(H as u64).pow(&[idx as u64, 0, 0, 0]); + * C::Scalar::from(bits as u64 + 2) + * C::Scalar::from(H as u64).pow(&[idx as u64, 0, 0, 0]); let x = *point.to_affine().coordinates().unwrap().x(); // Check that the interpolated x-coordinate matches the actual one. @@ -235,15 +230,10 @@ fn test_lagrange_coeffs(base: C, num_windows: usize) { // Compute the actual x-coordinate of the multiple [k * (8^84) - offset]B, // where offset = \sum_{j = 0}^{83} 2^{3j+1} let offset = (0..(num_windows - 1)).fold(C::Scalar::zero(), |acc, w| { - acc + C::Scalar::from_u64(2).pow(&[ - FIXED_BASE_WINDOW_SIZE as u64 * w as u64 + 1, - 0, - 0, - 0, - ]) + acc + C::Scalar::from(2).pow(&[FIXED_BASE_WINDOW_SIZE as u64 * w as u64 + 1, 0, 0, 0]) }); - let scalar = C::Scalar::from_u64(bits as u64) - * C::Scalar::from_u64(H as u64).pow(&[(num_windows - 1) as u64, 0, 0, 0]) + let scalar = C::Scalar::from(bits as u64) + * C::Scalar::from(H as u64).pow(&[(num_windows - 1) as u64, 0, 0, 0]) - offset; let point = base * scalar; let x = *point.to_affine().coordinates().unwrap().x(); @@ -265,8 +255,8 @@ fn test_zs_and_us(base: C, z: &[u64], u: &[[[u8; 32]; H]], num_w for (u, point) in u.iter().zip(window_points.iter()) { let y = *point.coordinates().unwrap().y(); let u = C::Base::from_bytes(u).unwrap(); - assert_eq!(C::Base::from_u64(*z) + y, u * u); // allow either square root - assert!(bool::from((C::Base::from_u64(*z) - y).sqrt().is_none())); + assert_eq!(C::Base::from(*z) + y, u * u); // allow either square root + assert!(bool::from((C::Base::from(*z) - y).sqrt().is_none())); } } } diff --git a/src/constants/load.rs b/src/constants/load.rs index e2743f26..22b2d80c 100644 --- a/src/constants/load.rs +++ b/src/constants/load.rs @@ -177,7 +177,7 @@ impl From<[u64; NUM_WINDOWS]> for Z { fn from(zs: [u64; NUM_WINDOWS]) -> Self { Self( zs.iter() - .map(|z| pallas::Base::from_u64(*z)) + .map(|z| pallas::Base::from(*z)) .collect::>() .into_boxed_slice() .try_into() @@ -194,7 +194,7 @@ impl From<[u64; NUM_WINDOWS_SHORT]> for ZShort { fn from(zs: [u64; NUM_WINDOWS_SHORT]) -> Self { Self( zs.iter() - .map(|z| pallas::Base::from_u64(*z)) + .map(|z| pallas::Base::from(*z)) .collect::>() .into_boxed_slice() .try_into() diff --git a/src/constants/util.rs b/src/constants/util.rs index b325091c..cc69c7dc 100644 --- a/src/constants/util.rs +++ b/src/constants/util.rs @@ -1,5 +1,5 @@ use ff::{Field, PrimeFieldBits}; -use halo2::arithmetic::{CurveAffine, FieldExt}; +use halo2::arithmetic::CurveAffine; /// Decompose a word `alpha` into `window_num_bits` bits (little-endian) /// For a window size of `w`, this returns [k_0, ..., k_n] where each `k_i` @@ -33,7 +33,7 @@ pub fn decompose_word( /// Evaluate y = f(x) given the coefficients of f(x) pub fn evaluate(x: u8, coeffs: &[C::Base]) -> C::Base { - let x = C::Base::from_u64(x as u64); + let x = C::Base::from(x as u64); coeffs .iter() .rev() diff --git a/src/primitives/poseidon.rs b/src/primitives/poseidon.rs index 1afe5cbe..f45cf6bf 100644 --- a/src/primitives/poseidon.rs +++ b/src/primitives/poseidon.rs @@ -370,7 +370,7 @@ mod tests { #[test] fn orchard_spec_equivalence() { - let message = [pallas::Base::from_u64(6), pallas::Base::from_u64(42)]; + let message = [pallas::Base::from(6), pallas::Base::from(42)]; let (round_constants, mds, _) = OrchardNullifier::constants(); diff --git a/src/primitives/sinsemilla/constants.rs b/src/primitives/sinsemilla/constants.rs index 47f3535f..8c767ed2 100644 --- a/src/primitives/sinsemilla/constants.rs +++ b/src/primitives/sinsemilla/constants.rs @@ -135,7 +135,7 @@ mod tests { #[test] fn inv_two_pow_k() { - let two_pow_k = pallas::Base::from_u64(1u64 << K); + let two_pow_k = pallas::Base::from(1u64 << K); let inv_two_pow_k = pallas::Base::from_bytes(&INV_TWO_POW_K).unwrap(); assert_eq!(two_pow_k * inv_two_pow_k, pallas::Base::one()); diff --git a/src/spec.rs b/src/spec.rs index 7d1cd698..264d2ffc 100644 --- a/src/spec.rs +++ b/src/spec.rs @@ -251,8 +251,8 @@ pub(crate) fn extract_p_bottom(point: CtOption) -> CtOption(bits: &[bool; L]) -> F { - F::from_u64(lebs2ip::(bits)) +pub fn lebs2ip_field(bits: &[bool; L]) -> F { + F::from(lebs2ip::(bits)) } /// The u64 integer represented by an L-bit little-endian bitstring. diff --git a/src/tree.rs b/src/tree.rs index d3101e73..14948db3 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -23,7 +23,7 @@ use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption}; // The uncommitted leaf is defined as pallas::Base(2). // lazy_static! { - static ref UNCOMMITTED_ORCHARD: pallas::Base = pallas::Base::from_u64(2); + static ref UNCOMMITTED_ORCHARD: pallas::Base = pallas::Base::from(2); pub(crate) static ref EMPTY_ROOTS: Vec = { iter::empty() .chain(Some(MerkleHashOrchard::empty_leaf())) diff --git a/src/value.rs b/src/value.rs index 7152643d..b3e626b6 100644 --- a/src/value.rs +++ b/src/value.rs @@ -23,7 +23,7 @@ use bitvec::{array::BitArray, order::Lsb0}; use ff::{Field, PrimeField}; use group::{Curve, Group, GroupEncoding}; use pasta_curves::{ - arithmetic::{CurveAffine, CurveExt, FieldExt}, + arithmetic::{CurveAffine, CurveExt}, pallas, }; use rand::RngCore; @@ -252,9 +252,9 @@ impl ValueCommitment { let abs_value = u64::try_from(value.0.abs()).expect("value must be in valid range"); let value = if value.0.is_negative() { - -pallas::Scalar::from_u64(abs_value) + -pallas::Scalar::from(abs_value) } else { - pallas::Scalar::from_u64(abs_value) + pallas::Scalar::from(abs_value) }; ValueCommitment(V * value + R * rcv.0) From 0378898289c0cd9901fe7330c41b13ca31a998d6 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 7 Dec 2021 18:02:03 +0000 Subject: [PATCH 47/59] Replace `FieldExt::{from, to}_bytes` with `PrimeField::{from, to}_repr` --- src/circuit/gadget/ecc/chip/mul.rs | 8 +++--- src/circuit/gadget/ecc/chip/mul_fixed.rs | 6 ++--- .../ecc/chip/mul_fixed/base_field_elem.rs | 8 +++--- .../gadget/ecc/chip/mul_fixed/short.rs | 10 +++----- src/circuit/gadget/sinsemilla.rs | 12 ++++++--- src/circuit/gadget/sinsemilla/chip.rs | 15 +++++------ .../gadget/sinsemilla/chip/hash_to_point.rs | 4 +-- src/circuit/gadget/sinsemilla/merkle.rs | 5 ++-- src/circuit/gadget/sinsemilla/merkle/chip.rs | 4 +-- src/circuit/gadget/utilities.rs | 12 ++++++--- .../gadget/utilities/lookup_range_check.rs | 4 ++- src/constants.rs | 4 ++- src/constants/commit_ivk_r.rs | 19 ++++++-------- src/constants/load.rs | 5 ++-- src/constants/note_commit_r.rs | 19 ++++++-------- src/constants/nullifier_k.rs | 19 ++++++-------- src/constants/spend_auth_g.rs | 16 ++++++------ src/constants/util.rs | 2 +- src/constants/value_commit_r.rs | 16 ++++++------ src/constants/value_commit_v.rs | 16 ++++++------ src/keys.rs | 25 +++++++++++-------- src/note/commitment.rs | 8 +++--- src/note/nullifier.rs | 8 +++--- src/note_encryption.rs | 4 +-- src/primitives/sinsemilla/constants.rs | 18 ++++++------- src/spec.rs | 6 ++--- src/tree.rs | 23 ++++++++--------- 27 files changed, 146 insertions(+), 150 deletions(-) diff --git a/src/circuit/gadget/ecc/chip/mul.rs b/src/circuit/gadget/ecc/chip/mul.rs index 863c8ca8..33746ac6 100644 --- a/src/circuit/gadget/ecc/chip/mul.rs +++ b/src/circuit/gadget/ecc/chip/mul.rs @@ -258,7 +258,7 @@ impl Config { let base = base.point(); let alpha = alpha .value() - .map(|alpha| pallas::Scalar::from_bytes(&alpha.to_bytes()).unwrap()); + .map(|alpha| pallas::Scalar::from_repr(alpha.to_repr()).unwrap()); let real_mul = base.zip(alpha).map(|(base, alpha)| base * alpha); let result = result.point(); @@ -431,7 +431,7 @@ fn decompose_for_scalar_mul(scalar: Option<&pallas::Base>) -> Vec> // the scalar field `F_q = 2^254 + t_q`. // Note that the addition `scalar + t_q` is not reduced. // - let scalar = U256::from_little_endian(&scalar.to_bytes()); + let scalar = U256::from_little_endian(&scalar.to_repr()); let t_q = U256::from_little_endian(&T_Q.to_le_bytes()); let k = scalar + t_q; @@ -463,7 +463,7 @@ fn decompose_for_scalar_mul(scalar: Option<&pallas::Base>) -> Vec> #[cfg(test)] pub mod tests { - use group::Curve; + use group::{ff::PrimeField, Curve}; use halo2::{ circuit::{Chip, Layouter}, plonk::Error, @@ -497,7 +497,7 @@ pub mod tests { ) -> Result<(), Error> { // Move scalar from base field into scalar field (which always fits // for Pallas). - let scalar = pallas::Scalar::from_bytes(&scalar_val.to_bytes()).unwrap(); + let scalar = pallas::Scalar::from_repr(scalar_val.to_repr()).unwrap(); let expected = NonIdentityPoint::new( chip, layouter.namespace(|| "expected point"), diff --git a/src/circuit/gadget/ecc/chip/mul_fixed.rs b/src/circuit/gadget/ecc/chip/mul_fixed.rs index 7e185000..b5e47338 100644 --- a/src/circuit/gadget/ecc/chip/mul_fixed.rs +++ b/src/circuit/gadget/ecc/chip/mul_fixed.rs @@ -8,7 +8,7 @@ use crate::constants::{ load::{NullifierK, OrchardFixedBase, OrchardFixedBasesFull, ValueCommitV, WindowUs}, }; -use group::Curve; +use group::{ff::PrimeField, Curve}; use halo2::{ circuit::{AssignedCell, Region}, plonk::{Advice, Column, ConstraintSystem, Error, Expression, Fixed, Selector, VirtualCells}, @@ -531,7 +531,7 @@ impl ScalarFixed { let word = z_cur .zip(z_next) .map(|(z_cur, z_next)| z_cur - z_next * *H_BASE); - word.map(|word| pallas::Scalar::from_bytes(&word.to_bytes()).unwrap()) + word.map(|word| pallas::Scalar::from_repr(word.to_repr()).unwrap()) }) .collect::>() }; @@ -543,7 +543,7 @@ impl ScalarFixed { .iter() .map(|bits| { bits.value() - .map(|value| pallas::Scalar::from_bytes(&value.to_bytes()).unwrap()) + .map(|value| pallas::Scalar::from_repr(value.to_repr()).unwrap()) }) .collect::>(), } diff --git a/src/circuit/gadget/ecc/chip/mul_fixed/base_field_elem.rs b/src/circuit/gadget/ecc/chip/mul_fixed/base_field_elem.rs index e72de865..99eefe39 100644 --- a/src/circuit/gadget/ecc/chip/mul_fixed/base_field_elem.rs +++ b/src/circuit/gadget/ecc/chip/mul_fixed/base_field_elem.rs @@ -214,13 +214,13 @@ impl Config { #[cfg(test)] // Check that the correct multiple is obtained. { - use group::Curve; + use group::{ff::PrimeField, Curve}; let base: super::OrchardFixedBases = base.into(); let scalar = &scalar .base_field_elem() .value() - .map(|scalar| pallas::Scalar::from_bytes(&scalar.to_bytes()).unwrap()); + .map(|scalar| pallas::Scalar::from_repr(scalar.to_repr()).unwrap()); let real_mul = scalar.map(|scalar| base.generator() * scalar); let result = result.point(); @@ -374,7 +374,7 @@ impl Config { #[cfg(test)] pub mod tests { - use group::Curve; + use group::{ff::PrimeField, Curve}; use halo2::{ circuit::{Chip, Layouter}, plonk::Error, @@ -421,7 +421,7 @@ pub mod tests { result: Point, ) -> Result<(), Error> { // Move scalar from base field into scalar field (which always fits for Pallas). - let scalar = pallas::Scalar::from_bytes(&scalar_val.to_bytes()).unwrap(); + let scalar = pallas::Scalar::from_repr(scalar_val.to_repr()).unwrap(); let expected = NonIdentityPoint::new( chip, layouter.namespace(|| "expected point"), diff --git a/src/circuit/gadget/ecc/chip/mul_fixed/short.rs b/src/circuit/gadget/ecc/chip/mul_fixed/short.rs index 19894147..8292da8a 100644 --- a/src/circuit/gadget/ecc/chip/mul_fixed/short.rs +++ b/src/circuit/gadget/ecc/chip/mul_fixed/short.rs @@ -187,8 +187,7 @@ impl Config { // Invalid values result in constraint failures which are // tested at the circuit-level. { - use group::Curve; - use pasta_curves::arithmetic::FieldExt; + use group::{ff::PrimeField, Curve}; if let (Some(magnitude), Some(sign)) = (scalar.magnitude.value(), scalar.sign.value()) { let magnitude_is_valid = magnitude <= &pallas::Base::from(0xFFFF_FFFF_FFFF_FFFFu64); @@ -200,8 +199,7 @@ impl Config { |(magnitude, sign)| { // Move magnitude from base field into scalar field (which always fits // for Pallas). - let magnitude = - pallas::Scalar::from_bytes(&magnitude.to_bytes()).unwrap(); + let magnitude = pallas::Scalar::from_repr(magnitude.to_repr()).unwrap(); let sign = if sign == &pallas::Base::one() { pallas::Scalar::one() @@ -229,7 +227,7 @@ impl Config { #[cfg(test)] pub mod tests { - use group::Curve; + use group::{ff::PrimeField, Curve}; use halo2::{ arithmetic::CurveAffine, circuit::{AssignedCell, Chip, Layouter}, @@ -330,7 +328,7 @@ pub mod tests { }; // Move from base field into scalar field let scalar = { - let magnitude = pallas::Scalar::from_bytes(&magnitude.to_bytes()).unwrap(); + let magnitude = pallas::Scalar::from_repr(magnitude.to_repr()).unwrap(); let sign = if *sign == pallas::Base::one() { pallas::Scalar::one() } else { diff --git a/src/circuit/gadget/sinsemilla.rs b/src/circuit/gadget/sinsemilla.rs index 20d8259a..5412c3ab 100644 --- a/src/circuit/gadget/sinsemilla.rs +++ b/src/circuit/gadget/sinsemilla.rs @@ -5,8 +5,8 @@ use crate::circuit::gadget::{ }; use ff::PrimeField; use halo2::{circuit::Layouter, plonk::Error}; -use pasta_curves::arithmetic::{CurveAffine, FieldExt}; -use std::{convert::TryInto, fmt::Debug}; +use pasta_curves::arithmetic::CurveAffine; +use std::fmt::Debug; pub mod chip; pub mod commit_ivk; @@ -207,7 +207,13 @@ where .map(|byte| byte.iter().rev().fold(0u8, |acc, bit| acc * 2 + *bit as u8)) .collect() }); - bytes.map(|bytes| C::Base::from_bytes(&bytes.try_into().unwrap()).unwrap()) + bytes.map(|bytes| { + let mut repr = ::Repr::default(); + // The above code assumes the byte representation is 256 bits. + assert_eq!(repr.as_ref().len(), 32); + repr.as_mut().copy_from_slice(&bytes); + C::Base::from_repr(repr).unwrap() + }) }; let piece_value = to_base_field(bitstring); diff --git a/src/circuit/gadget/sinsemilla/chip.rs b/src/circuit/gadget/sinsemilla/chip.rs index c3b5267a..f2a7ff1e 100644 --- a/src/circuit/gadget/sinsemilla/chip.rs +++ b/src/circuit/gadget/sinsemilla/chip.rs @@ -12,8 +12,9 @@ use crate::{ }, }; +use group::ff::PrimeField; use halo2::{ - arithmetic::{CurveAffine, FieldExt}, + arithmetic::CurveAffine, circuit::{AssignedCell, Chip, Layouter}, plonk::{ Advice, Column, ConstraintSystem, Error, Expression, Fixed, Selector, TableColumn, @@ -305,18 +306,18 @@ impl HashDomains for SinsemillaHashDomains { fn Q(&self) -> pallas::Affine { match self { SinsemillaHashDomains::CommitIvk => pallas::Affine::from_xy( - pallas::Base::from_bytes(&Q_COMMIT_IVK_M_GENERATOR.0).unwrap(), - pallas::Base::from_bytes(&Q_COMMIT_IVK_M_GENERATOR.1).unwrap(), + pallas::Base::from_repr(Q_COMMIT_IVK_M_GENERATOR.0).unwrap(), + pallas::Base::from_repr(Q_COMMIT_IVK_M_GENERATOR.1).unwrap(), ) .unwrap(), SinsemillaHashDomains::NoteCommit => pallas::Affine::from_xy( - pallas::Base::from_bytes(&Q_NOTE_COMMITMENT_M_GENERATOR.0).unwrap(), - pallas::Base::from_bytes(&Q_NOTE_COMMITMENT_M_GENERATOR.1).unwrap(), + pallas::Base::from_repr(Q_NOTE_COMMITMENT_M_GENERATOR.0).unwrap(), + pallas::Base::from_repr(Q_NOTE_COMMITMENT_M_GENERATOR.1).unwrap(), ) .unwrap(), SinsemillaHashDomains::MerkleCrh => pallas::Affine::from_xy( - pallas::Base::from_bytes(&Q_MERKLE_CRH.0).unwrap(), - pallas::Base::from_bytes(&Q_MERKLE_CRH.1).unwrap(), + pallas::Base::from_repr(Q_MERKLE_CRH.0).unwrap(), + pallas::Base::from_repr(Q_MERKLE_CRH.1).unwrap(), ) .unwrap(), } diff --git a/src/circuit/gadget/sinsemilla/chip/hash_to_point.rs b/src/circuit/gadget/sinsemilla/chip/hash_to_point.rs index dcfb3522..517e2202 100644 --- a/src/circuit/gadget/sinsemilla/chip/hash_to_point.rs +++ b/src/circuit/gadget/sinsemilla/chip/hash_to_point.rs @@ -7,7 +7,7 @@ use halo2::{ plonk::Error, }; -use ff::{Field, PrimeFieldBits}; +use group::ff::{Field, PrimeField, PrimeFieldBits}; use pasta_curves::{ arithmetic::{CurveAffine, FieldExt}, pallas, @@ -284,7 +284,7 @@ impl SinsemillaChip { // We end up with z_n = 0. (z_n is not directly encoded as a cell value; // it is implicitly taken as 0 by adjusting the definition of m_{i+1}.) let mut z = piece.field_elem(); - let inv_2_k = pallas::Base::from_bytes(&INV_TWO_POW_K).unwrap(); + let inv_2_k = pallas::Base::from_repr(INV_TWO_POW_K).unwrap(); // We do not assign the final z_n as it is constrained to be zero. for (idx, word) in words[0..(words.len() - 1)].iter().enumerate() { diff --git a/src/circuit/gadget/sinsemilla/merkle.rs b/src/circuit/gadget/sinsemilla/merkle.rs index c28f83e4..d83484d7 100644 --- a/src/circuit/gadget/sinsemilla/merkle.rs +++ b/src/circuit/gadget/sinsemilla/merkle.rs @@ -146,6 +146,7 @@ pub mod tests { tree, }; + use group::ff::PrimeField; use halo2::{ arithmetic::FieldExt, circuit::{Layouter, SimpleFloorPlanner}, @@ -260,8 +261,8 @@ pub mod tests { // The expected final root let final_root = { let path = tree::MerklePath::new(leaf_pos, self.merkle_path.unwrap()); - let leaf = ExtractedNoteCommitment::from_bytes(&self.leaf.unwrap().to_bytes()) - .unwrap(); + let leaf = + ExtractedNoteCommitment::from_bytes(&self.leaf.unwrap().to_repr()).unwrap(); path.root(leaf) }; diff --git a/src/circuit/gadget/sinsemilla/merkle/chip.rs b/src/circuit/gadget/sinsemilla/merkle/chip.rs index 609eb75e..a4230668 100644 --- a/src/circuit/gadget/sinsemilla/merkle/chip.rs +++ b/src/circuit/gadget/sinsemilla/merkle/chip.rs @@ -323,7 +323,7 @@ impl MerkleInstructions(l as u64); @@ -347,7 +347,7 @@ impl MerkleInstructions(a: Expression, b: Expression, c: Expression /// Takes a specified subsequence of the little-endian bit representation of a field element. /// The bits are numbered from 0 for the LSB. -pub fn bitrange_subset(field_elem: &F, bitrange: Range) -> F { +pub fn bitrange_subset(field_elem: &F, bitrange: Range) -> F { assert!(bitrange.end <= F::NUM_BITS as usize); let bits: Vec = field_elem @@ -103,7 +103,11 @@ pub fn bitrange_subset(field_elem: &F, bitrange: R .map(|byte| byte.iter().rev().fold(0u8, |acc, bit| acc * 2 + *bit as u8)) .collect(); - F::from_bytes(&bytearray.try_into().unwrap()).unwrap() + let mut repr = F::Repr::default(); + // The above code assumes the byte representation is 256 bits. + assert_eq!(repr.as_ref().len(), 32); + repr.as_mut().copy_from_slice(&bytearray); + F::from_repr(repr).unwrap() } /// Check that an expression is in the small range [0..range), @@ -261,7 +265,7 @@ mod tests { .to_little_endian(&mut range_shift); range_shift }; - sum += subset * pallas::Base::from_bytes(&range_shift).unwrap(); + sum += subset * pallas::Base::from_repr(range_shift).unwrap(); } assert_eq!(field_elem, sum); }; diff --git a/src/circuit/gadget/utilities/lookup_range_check.rs b/src/circuit/gadget/utilities/lookup_range_check.rs index 4d1ad033..65f0eb81 100644 --- a/src/circuit/gadget/utilities/lookup_range_check.rs +++ b/src/circuit/gadget/utilities/lookup_range_check.rs @@ -431,7 +431,9 @@ mod tests { .collect::>() }; let expected_zs = { - let inv_two_pow_k = F::from_bytes(&INV_TWO_POW_K).unwrap(); + let mut repr = F::Repr::default(); + repr.as_mut().copy_from_slice(&INV_TWO_POW_K); + let inv_two_pow_k = F::from_repr(repr).unwrap(); chunks.iter().fold(vec![element], |mut zs, a_i| { // z_{i + 1} = (z_i - a_i) / 2^{K} let z = (zs[zs.len() - 1] - a_i) * inv_two_pow_k; diff --git a/src/constants.rs b/src/constants.rs index c417a078..0368e6ed 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -254,7 +254,9 @@ fn test_zs_and_us(base: C, z: &[u64], u: &[[[u8; 32]; H]], num_w for ((u, z), window_points) in u.iter().zip(z.iter()).zip(window_table) { for (u, point) in u.iter().zip(window_points.iter()) { let y = *point.coordinates().unwrap().y(); - let u = C::Base::from_bytes(u).unwrap(); + let mut u_repr = ::Repr::default(); + u_repr.as_mut().copy_from_slice(u); + let u = C::Base::from_repr(u_repr).unwrap(); assert_eq!(C::Base::from(*z) + y, u * u); // allow either square root assert!(bool::from((C::Base::from(*z) - y).sqrt().is_none())); } diff --git a/src/constants/commit_ivk_r.rs b/src/constants/commit_ivk_r.rs index c0e0b508..976ed22e 100644 --- a/src/constants/commit_ivk_r.rs +++ b/src/constants/commit_ivk_r.rs @@ -1,7 +1,5 @@ -use pasta_curves::{ - arithmetic::{CurveAffine, FieldExt}, - pallas, -}; +use group::ff::PrimeField; +use pasta_curves::{arithmetic::CurveAffine, pallas}; /// Generator used in SinsemillaCommit randomness for IVK commitment pub const GENERATOR: ([u8; 32], [u8; 32]) = ( @@ -2922,8 +2920,8 @@ pub const U: [[[u8; 32]; super::H]; super::NUM_WINDOWS] = [ pub fn generator() -> pallas::Affine { pallas::Affine::from_xy( - pallas::Base::from_bytes(&GENERATOR.0).unwrap(), - pallas::Base::from_bytes(&GENERATOR.1).unwrap(), + pallas::Base::from_repr(GENERATOR.0).unwrap(), + pallas::Base::from_repr(GENERATOR.1).unwrap(), ) .unwrap() } @@ -2936,10 +2934,7 @@ mod tests { use super::*; use crate::primitives::sinsemilla::CommitDomain; use group::Curve; - use pasta_curves::{ - arithmetic::{CurveAffine, FieldExt}, - pallas, - }; + use pasta_curves::{arithmetic::CurveAffine, pallas}; #[test] fn generator() { @@ -2947,8 +2942,8 @@ mod tests { let point = domain.R(); let coords = point.to_affine().coordinates().unwrap(); - assert_eq!(*coords.x(), pallas::Base::from_bytes(&GENERATOR.0).unwrap()); - assert_eq!(*coords.y(), pallas::Base::from_bytes(&GENERATOR.1).unwrap()); + assert_eq!(*coords.x(), pallas::Base::from_repr(GENERATOR.0).unwrap()); + assert_eq!(*coords.y(), pallas::Base::from_repr(GENERATOR.1).unwrap()); } #[test] diff --git a/src/constants/load.rs b/src/constants/load.rs index 22b2d80c..5368a962 100644 --- a/src/constants/load.rs +++ b/src/constants/load.rs @@ -1,7 +1,8 @@ use std::convert::TryInto; use crate::constants::{self, compute_lagrange_coeffs, H, NUM_WINDOWS, NUM_WINDOWS_SHORT}; -use pasta_curves::{arithmetic::FieldExt, pallas}; +use group::ff::PrimeField; +use pasta_curves::pallas; #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum OrchardFixedBasesFull { @@ -212,7 +213,7 @@ impl From<&[[u8; 32]; H]> for WindowUs { Self( window_us .iter() - .map(|u| pallas::Base::from_bytes(u).unwrap()) + .map(|u| pallas::Base::from_repr(*u).unwrap()) .collect::>() .into_boxed_slice() .try_into() diff --git a/src/constants/note_commit_r.rs b/src/constants/note_commit_r.rs index 4a12734d..d2dde504 100644 --- a/src/constants/note_commit_r.rs +++ b/src/constants/note_commit_r.rs @@ -1,7 +1,5 @@ -use pasta_curves::{ - arithmetic::{CurveAffine, FieldExt}, - pallas, -}; +use group::ff::PrimeField; +use pasta_curves::{arithmetic::CurveAffine, pallas}; /// Generator used in SinsemillaCommit randomness for note commitment pub const GENERATOR: ([u8; 32], [u8; 32]) = ( @@ -2922,8 +2920,8 @@ pub const U: [[[u8; 32]; super::H]; super::NUM_WINDOWS] = [ pub fn generator() -> pallas::Affine { pallas::Affine::from_xy( - pallas::Base::from_bytes(&GENERATOR.0).unwrap(), - pallas::Base::from_bytes(&GENERATOR.1).unwrap(), + pallas::Base::from_repr(GENERATOR.0).unwrap(), + pallas::Base::from_repr(GENERATOR.1).unwrap(), ) .unwrap() } @@ -2936,10 +2934,7 @@ mod tests { use super::*; use crate::primitives::sinsemilla::CommitDomain; use group::Curve; - use pasta_curves::{ - arithmetic::{CurveAffine, FieldExt}, - pallas, - }; + use pasta_curves::{arithmetic::CurveAffine, pallas}; #[test] fn generator() { @@ -2947,8 +2942,8 @@ mod tests { let point = domain.R(); let coords = point.to_affine().coordinates().unwrap(); - assert_eq!(*coords.x(), pallas::Base::from_bytes(&GENERATOR.0).unwrap()); - assert_eq!(*coords.y(), pallas::Base::from_bytes(&GENERATOR.1).unwrap()); + assert_eq!(*coords.x(), pallas::Base::from_repr(GENERATOR.0).unwrap()); + assert_eq!(*coords.y(), pallas::Base::from_repr(GENERATOR.1).unwrap()); } #[test] diff --git a/src/constants/nullifier_k.rs b/src/constants/nullifier_k.rs index 37db6fda..47f69068 100644 --- a/src/constants/nullifier_k.rs +++ b/src/constants/nullifier_k.rs @@ -1,7 +1,5 @@ -use pasta_curves::{ - arithmetic::{CurveAffine, FieldExt}, - pallas, -}; +use group::ff::PrimeField; +use pasta_curves::{arithmetic::CurveAffine, pallas}; pub const GENERATOR: ([u8; 32], [u8; 32]) = ( [ @@ -2921,8 +2919,8 @@ pub const U: [[[u8; 32]; super::H]; super::NUM_WINDOWS] = [ pub fn generator() -> pallas::Affine { pallas::Affine::from_xy( - pallas::Base::from_bytes(&GENERATOR.0).unwrap(), - pallas::Base::from_bytes(&GENERATOR.1).unwrap(), + pallas::Base::from_repr(GENERATOR.0).unwrap(), + pallas::Base::from_repr(GENERATOR.1).unwrap(), ) .unwrap() } @@ -2934,10 +2932,7 @@ mod tests { }; use super::*; use group::Curve; - use pasta_curves::{ - arithmetic::{CurveExt, FieldExt}, - pallas, - }; + use pasta_curves::{arithmetic::CurveExt, pallas}; #[test] fn generator() { @@ -2945,8 +2940,8 @@ mod tests { let point = hasher(b"K"); let coords = point.to_affine().coordinates().unwrap(); - assert_eq!(*coords.x(), pallas::Base::from_bytes(&GENERATOR.0).unwrap()); - assert_eq!(*coords.y(), pallas::Base::from_bytes(&GENERATOR.1).unwrap()); + assert_eq!(*coords.x(), pallas::Base::from_repr(GENERATOR.0).unwrap()); + assert_eq!(*coords.y(), pallas::Base::from_repr(GENERATOR.1).unwrap()); } #[test] diff --git a/src/constants/spend_auth_g.rs b/src/constants/spend_auth_g.rs index 41b99c90..6deba8f6 100644 --- a/src/constants/spend_auth_g.rs +++ b/src/constants/spend_auth_g.rs @@ -1,7 +1,5 @@ -use pasta_curves::{ - arithmetic::{CurveAffine, FieldExt}, - pallas, -}; +use group::ff::PrimeField; +use pasta_curves::{arithmetic::CurveAffine, pallas}; /// The value commitment is used to check balance between inputs and outputs. The value is /// placed over this generator. @@ -2923,8 +2921,8 @@ pub const U: [[[u8; 32]; super::H]; super::NUM_WINDOWS] = [ pub fn generator() -> pallas::Affine { pallas::Affine::from_xy( - pallas::Base::from_bytes(&GENERATOR.0).unwrap(), - pallas::Base::from_bytes(&GENERATOR.1).unwrap(), + pallas::Base::from_repr(GENERATOR.0).unwrap(), + pallas::Base::from_repr(GENERATOR.1).unwrap(), ) .unwrap() } @@ -2937,7 +2935,7 @@ mod tests { use super::*; use group::Curve; use pasta_curves::{ - arithmetic::{CurveAffine, CurveExt, FieldExt}, + arithmetic::{CurveAffine, CurveExt}, pallas, }; @@ -2947,8 +2945,8 @@ mod tests { let point = hasher(b"G"); let coords = point.to_affine().coordinates().unwrap(); - assert_eq!(*coords.x(), pallas::Base::from_bytes(&GENERATOR.0).unwrap()); - assert_eq!(*coords.y(), pallas::Base::from_bytes(&GENERATOR.1).unwrap()); + assert_eq!(*coords.x(), pallas::Base::from_repr(GENERATOR.0).unwrap()); + assert_eq!(*coords.y(), pallas::Base::from_repr(GENERATOR.1).unwrap()); } #[test] diff --git a/src/constants/util.rs b/src/constants/util.rs index cc69c7dc..b68404e9 100644 --- a/src/constants/util.rs +++ b/src/constants/util.rs @@ -102,7 +102,7 @@ mod tests { let bytes: Vec = bits.chunks_exact(8).map(|chunk| chunk.iter().rev().fold(0, |acc, b| (acc << 1) + (*b as u8))).collect(); // Check that original scalar is recovered from decomposition - assert_eq!(scalar, pallas::Scalar::from_bytes(&bytes.try_into().unwrap()).unwrap()); + assert_eq!(scalar, pallas::Scalar::from_repr(bytes.try_into().unwrap()).unwrap()); } } } diff --git a/src/constants/value_commit_r.rs b/src/constants/value_commit_r.rs index 402df337..b12030f0 100644 --- a/src/constants/value_commit_r.rs +++ b/src/constants/value_commit_r.rs @@ -1,7 +1,5 @@ -use pasta_curves::{ - arithmetic::{CurveAffine, FieldExt}, - pallas, -}; +use group::ff::PrimeField; +use pasta_curves::{arithmetic::CurveAffine, pallas}; /// The value commitment is used to check balance between inputs and outputs. The value is /// placed over this generator. @@ -2923,8 +2921,8 @@ pub const U: [[[u8; 32]; super::H]; super::NUM_WINDOWS] = [ pub fn generator() -> pallas::Affine { pallas::Affine::from_xy( - pallas::Base::from_bytes(&GENERATOR.0).unwrap(), - pallas::Base::from_bytes(&GENERATOR.1).unwrap(), + pallas::Base::from_repr(GENERATOR.0).unwrap(), + pallas::Base::from_repr(GENERATOR.1).unwrap(), ) .unwrap() } @@ -2937,7 +2935,7 @@ mod tests { use super::*; use group::Curve; use pasta_curves::{ - arithmetic::{CurveAffine, CurveExt, FieldExt}, + arithmetic::{CurveAffine, CurveExt}, pallas, }; @@ -2947,8 +2945,8 @@ mod tests { let point = hasher(b"r"); let coords = point.to_affine().coordinates().unwrap(); - assert_eq!(*coords.x(), pallas::Base::from_bytes(&GENERATOR.0).unwrap()); - assert_eq!(*coords.y(), pallas::Base::from_bytes(&GENERATOR.1).unwrap()); + assert_eq!(*coords.x(), pallas::Base::from_repr(GENERATOR.0).unwrap()); + assert_eq!(*coords.y(), pallas::Base::from_repr(GENERATOR.1).unwrap()); } #[test] diff --git a/src/constants/value_commit_v.rs b/src/constants/value_commit_v.rs index 7ffc9899..c17bdaed 100644 --- a/src/constants/value_commit_v.rs +++ b/src/constants/value_commit_v.rs @@ -1,7 +1,5 @@ -use pasta_curves::{ - arithmetic::{CurveAffine, FieldExt}, - pallas, -}; +use group::ff::PrimeField; +use pasta_curves::{arithmetic::CurveAffine, pallas}; /// The value commitment is used to check balance between inputs and outputs. The value is /// placed over this generator. @@ -776,8 +774,8 @@ pub const U_SHORT: [[[u8; 32]; super::H]; super::NUM_WINDOWS_SHORT] = [ pub fn generator() -> pallas::Affine { pallas::Affine::from_xy( - pallas::Base::from_bytes(&GENERATOR.0).unwrap(), - pallas::Base::from_bytes(&GENERATOR.1).unwrap(), + pallas::Base::from_repr(GENERATOR.0).unwrap(), + pallas::Base::from_repr(GENERATOR.1).unwrap(), ) .unwrap() } @@ -790,7 +788,7 @@ mod tests { use super::*; use group::Curve; use pasta_curves::{ - arithmetic::{CurveAffine, CurveExt, FieldExt}, + arithmetic::{CurveAffine, CurveExt}, pallas, }; @@ -800,8 +798,8 @@ mod tests { let point = hasher(b"v"); let coords = point.to_affine().coordinates().unwrap(); - assert_eq!(*coords.x(), pallas::Base::from_bytes(&GENERATOR.0).unwrap()); - assert_eq!(*coords.y(), pallas::Base::from_bytes(&GENERATOR.1).unwrap()); + assert_eq!(*coords.x(), pallas::Base::from_repr(GENERATOR.0).unwrap()); + assert_eq!(*coords.y(), pallas::Base::from_repr(GENERATOR.1).unwrap()); } #[test] diff --git a/src/keys.rs b/src/keys.rs index 49e9153b..eaba70c1 100644 --- a/src/keys.rs +++ b/src/keys.rs @@ -7,8 +7,11 @@ use std::mem; use aes::Aes256; use blake2b_simd::{Hash as Blake2bHash, Params}; use fpe::ff1::{BinaryNumeralString, FF1}; -use group::{ff::Field, prime::PrimeCurveAffine, Curve, GroupEncoding}; -use halo2::arithmetic::FieldExt; +use group::{ + ff::{Field, PrimeField}, + prime::PrimeCurveAffine, + Curve, GroupEncoding, +}; use pasta_curves::pallas; use rand::RngCore; use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption}; @@ -118,10 +121,10 @@ impl From<&SpendingKey> for SpendAuthorizingKey { // SpendingKey cannot be constructed such that this assertion would fail. assert!(!bool::from(ask.is_zero())); // TODO: Add TryFrom for SpendAuthorizingKey. - let ret = SpendAuthorizingKey(ask.to_bytes().try_into().unwrap()); + let ret = SpendAuthorizingKey(ask.to_repr().try_into().unwrap()); // If the last bit of repr_P(ak) is 1, negate ask. if (<[u8; 32]>::from(SpendValidatingKey::from(&ret).0)[31] >> 7) == 1 { - SpendAuthorizingKey((-ask).to_bytes().try_into().unwrap()) + SpendAuthorizingKey((-ask).to_repr().try_into().unwrap()) } else { ret } @@ -221,7 +224,7 @@ impl NullifierDerivingKey { pub(crate) fn from_bytes(bytes: &[u8]) -> Option { let nk_bytes = <[u8; 32]>::try_from(bytes).ok()?; - let nk = pallas::Base::from_bytes(&nk_bytes).map(NullifierDerivingKey); + let nk = pallas::Base::from_repr(nk_bytes).map(NullifierDerivingKey); if nk.is_some().into() { Some(nk.unwrap()) } else { @@ -256,7 +259,7 @@ impl CommitIvkRandomness { pub(crate) fn from_bytes(bytes: &[u8]) -> Option { let rivk_bytes = <[u8; 32]>::try_from(bytes).ok()?; - let rivk = pallas::Scalar::from_bytes(&rivk_bytes).map(CommitIvkRandomness); + let rivk = pallas::Scalar::from_repr(rivk_bytes).map(CommitIvkRandomness); if rivk.is_some().into() { Some(rivk.unwrap()) } else { @@ -315,8 +318,8 @@ impl FullViewingKey { /// /// [orchardkeycomponents]: https://zips.z.cash/protocol/nu5.pdf#orchardkeycomponents fn derive_dk_ovk(&self) -> (DiversifierKey, OutgoingViewingKey) { - let k = self.rivk.0.to_bytes(); - let b = [(&self.ak.0).into(), self.nk.0.to_bytes()]; + let k = self.rivk.0.to_repr(); + let b = [(&self.ak.0).into(), self.nk.0.to_repr()]; let r = PrfExpand::OrchardDkOvk.with_ad_slices(&k, &[&b[0][..], &b[1][..]]); ( DiversifierKey(r[..32].try_into().unwrap()), @@ -346,8 +349,8 @@ impl FullViewingKey { pub fn write(&self, mut writer: W) -> io::Result<()> { let ak_raw: [u8; 32] = self.ak.0.clone().into(); writer.write_all(&ak_raw)?; - writer.write_all(&self.nk.0.to_bytes())?; - writer.write_all(&self.rivk.0.to_bytes())?; + writer.write_all(&self.nk.0.to_repr())?; + writer.write_all(&self.rivk.0.to_repr())?; Ok(()) } @@ -545,7 +548,7 @@ impl IncomingViewingKey { pub fn to_bytes(&self) -> [u8; 64] { let mut result = [0u8; 64]; result[..32].copy_from_slice(self.dk.to_bytes()); - result[32..].copy_from_slice(&self.ivk.0.to_bytes()); + result[32..].copy_from_slice(&self.ivk.0.to_repr()); result } diff --git a/src/note/commitment.rs b/src/note/commitment.rs index d3a7dff8..a8109efb 100644 --- a/src/note/commitment.rs +++ b/src/note/commitment.rs @@ -1,8 +1,8 @@ use std::iter; use bitvec::{array::BitArray, order::Lsb0}; -use ff::PrimeFieldBits; -use pasta_curves::{arithmetic::FieldExt, pallas}; +use group::ff::{PrimeField, PrimeFieldBits}; +use pasta_curves::pallas; use subtle::{ConstantTimeEq, CtOption}; use crate::{ @@ -72,12 +72,12 @@ impl ExtractedNoteCommitment { /// /// [cmxcanon]: https://zips.z.cash/protocol/protocol.pdf#actionencodingandconsensus pub fn from_bytes(bytes: &[u8; 32]) -> CtOption { - pallas::Base::from_bytes(bytes).map(ExtractedNoteCommitment) + pallas::Base::from_repr(*bytes).map(ExtractedNoteCommitment) } /// Serialize the value commitment to its canonical byte representation. pub fn to_bytes(self) -> [u8; 32] { - self.0.to_bytes() + self.0.to_repr() } } diff --git a/src/note/nullifier.rs b/src/note/nullifier.rs index 6090f335..88192781 100644 --- a/src/note/nullifier.rs +++ b/src/note/nullifier.rs @@ -1,6 +1,6 @@ -use group::Group; +use group::{ff::PrimeField, Group}; use halo2::arithmetic::CurveExt; -use pasta_curves::{arithmetic::FieldExt, pallas}; +use pasta_curves::pallas; use rand::RngCore; use subtle::CtOption; @@ -33,12 +33,12 @@ impl Nullifier { /// Deserialize the nullifier from a byte array. pub fn from_bytes(bytes: &[u8; 32]) -> CtOption { - pallas::Base::from_bytes(bytes).map(Nullifier) + pallas::Base::from_repr(*bytes).map(Nullifier) } /// Serialize the nullifier to its canonical byte representation. pub fn to_bytes(self) -> [u8; 32] { - self.0.to_bytes() + self.0.to_repr() } /// $DeriveNullifier$. diff --git a/src/note_encryption.rs b/src/note_encryption.rs index d6d51063..642f05e9 100644 --- a/src/note_encryption.rs +++ b/src/note_encryption.rs @@ -3,7 +3,7 @@ use std::{convert::TryInto, fmt}; use blake2b_simd::{Hash, Params}; -use halo2::arithmetic::FieldExt; +use group::ff::PrimeField; use zcash_note_encryption::{ BatchDomain, Domain, EphemeralKeyBytes, NotePlaintextBytes, NoteValidity, OutPlaintextBytes, OutgoingCipherKey, ShieldedOutput, COMPACT_NOTE_SIZE, NOTE_PLAINTEXT_SIZE, OUT_PLAINTEXT_SIZE, @@ -170,7 +170,7 @@ impl Domain for OrchardDomain { ) -> OutPlaintextBytes { let mut op = [0; OUT_PLAINTEXT_SIZE]; op[..32].copy_from_slice(¬e.recipient().pk_d().to_bytes()); - op[32..].copy_from_slice(&esk.0.to_bytes()); + op[32..].copy_from_slice(&esk.0.to_repr()); OutPlaintextBytes(op) } diff --git a/src/primitives/sinsemilla/constants.rs b/src/primitives/sinsemilla/constants.rs index 8c767ed2..d09c283b 100644 --- a/src/primitives/sinsemilla/constants.rs +++ b/src/primitives/sinsemilla/constants.rs @@ -66,8 +66,8 @@ mod tests { use crate::constants::{ COMMIT_IVK_PERSONALIZATION, MERKLE_CRH_PERSONALIZATION, NOTE_COMMITMENT_PERSONALIZATION, }; - use group::Curve; - use halo2::arithmetic::{CurveAffine, CurveExt, FieldExt}; + use group::{ff::PrimeField, Curve}; + use halo2::arithmetic::{CurveAffine, CurveExt}; use halo2::pasta::pallas; #[test] @@ -93,11 +93,11 @@ mod tests { assert_eq!( *coords.x(), - pallas::Base::from_bytes(&Q_NOTE_COMMITMENT_M_GENERATOR.0).unwrap() + pallas::Base::from_repr(Q_NOTE_COMMITMENT_M_GENERATOR.0).unwrap() ); assert_eq!( *coords.y(), - pallas::Base::from_bytes(&Q_NOTE_COMMITMENT_M_GENERATOR.1).unwrap() + pallas::Base::from_repr(Q_NOTE_COMMITMENT_M_GENERATOR.1).unwrap() ); } @@ -109,11 +109,11 @@ mod tests { assert_eq!( *coords.x(), - pallas::Base::from_bytes(&Q_COMMIT_IVK_M_GENERATOR.0).unwrap() + pallas::Base::from_repr(Q_COMMIT_IVK_M_GENERATOR.0).unwrap() ); assert_eq!( *coords.y(), - pallas::Base::from_bytes(&Q_COMMIT_IVK_M_GENERATOR.1).unwrap() + pallas::Base::from_repr(Q_COMMIT_IVK_M_GENERATOR.1).unwrap() ); } @@ -125,18 +125,18 @@ mod tests { assert_eq!( *coords.x(), - pallas::Base::from_bytes(&Q_MERKLE_CRH.0).unwrap() + pallas::Base::from_repr(Q_MERKLE_CRH.0).unwrap() ); assert_eq!( *coords.y(), - pallas::Base::from_bytes(&Q_MERKLE_CRH.1).unwrap() + pallas::Base::from_repr(Q_MERKLE_CRH.1).unwrap() ); } #[test] fn inv_two_pow_k() { let two_pow_k = pallas::Base::from(1u64 << K); - let inv_two_pow_k = pallas::Base::from_bytes(&INV_TWO_POW_K).unwrap(); + let inv_two_pow_k = pallas::Base::from_repr(INV_TWO_POW_K).unwrap(); assert_eq!(two_pow_k * inv_two_pow_k, pallas::Base::one()); } diff --git a/src/spec.rs b/src/spec.rs index 264d2ffc..adb76bb2 100644 --- a/src/spec.rs +++ b/src/spec.rs @@ -70,11 +70,11 @@ impl ConditionallySelectable for NonZeroPallasBase { impl NonZeroPallasBase { pub(crate) fn from_bytes(bytes: &[u8; 32]) -> CtOption { - pallas::Base::from_bytes(bytes).and_then(NonZeroPallasBase::from_base) + pallas::Base::from_repr(*bytes).and_then(NonZeroPallasBase::from_base) } pub(crate) fn to_bytes(&self) -> [u8; 32] { - self.0.to_bytes() + self.0.to_repr() } pub(crate) fn from_base(b: pallas::Base) -> CtOption { @@ -116,7 +116,7 @@ impl ConditionallySelectable for NonZeroPallasScalar { impl NonZeroPallasScalar { pub(crate) fn from_bytes(bytes: &[u8; 32]) -> CtOption { - pallas::Scalar::from_bytes(bytes).and_then(NonZeroPallasScalar::from_scalar) + pallas::Scalar::from_repr(*bytes).and_then(NonZeroPallasScalar::from_scalar) } pub(crate) fn from_scalar(s: pallas::Scalar) -> CtOption { diff --git a/src/tree.rs b/src/tree.rs index 14948db3..e111ba26 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -9,7 +9,7 @@ use crate::{ primitives::sinsemilla::{i2lebsp_k, HashDomain}, }; use incrementalmerkletree::{Altitude, Hashable}; -use pasta_curves::{arithmetic::FieldExt, pallas}; +use pasta_curves::pallas; use ff::{Field, PrimeField, PrimeFieldBits}; use lazy_static::lazy_static; @@ -172,7 +172,7 @@ impl MerkleHashOrchard { /// Convert this digest to its canonical byte representation. pub fn to_bytes(&self) -> [u8; 32] { - self.0.to_bytes() + self.0.to_repr() } /// Parses a incremental tree leaf digest from the bytes of @@ -181,7 +181,7 @@ impl MerkleHashOrchard { /// Returns the empty `CtOption` if the provided bytes represent /// a non-canonical encoding. pub fn from_bytes(bytes: &[u8; 32]) -> CtOption { - pallas::Base::from_bytes(bytes).map(MerkleHashOrchard) + pallas::Base::from_repr(*bytes).map(MerkleHashOrchard) } } @@ -199,7 +199,7 @@ impl std::cmp::Eq for MerkleHashOrchard {} impl std::hash::Hash for MerkleHashOrchard { fn hash(&self, state: &mut H) { >::from(self.0) - .map(|b| b.to_bytes()) + .map(|b| b.to_repr()) .hash(state) } } @@ -275,7 +275,9 @@ pub mod testing { #[cfg(test)] use crate::tree::{MerkleHashOrchard, EMPTY_ROOTS}; #[cfg(test)] - use pasta_curves::{arithmetic::FieldExt, pallas}; + use group::ff::PrimeField; + #[cfg(test)] + use pasta_curves::pallas; #[cfg(test)] use std::convert::TryInto; @@ -296,7 +298,7 @@ pub mod testing { tree.append(&cmx); tree.witness(); - assert_eq!(tree.root().0, pallas::Base::from_bytes(&tv.root).unwrap()); + assert_eq!(tree.root().0, pallas::Base::from_repr(tv.root).unwrap()); // Check paths for all leaves up to this point. The test vectors include paths // for not-yet-appended leaves (using UNCOMMITTED_ORCHARD as the leaf value), @@ -327,7 +329,7 @@ pub mod testing { assert_eq!( MerkleHashOrchard::empty_root(Altitude::from(altitude as u8)) .0 - .to_bytes(), + .to_repr(), *tv_root, "Empty root mismatch at altitude {}", altitude @@ -378,12 +380,9 @@ pub mod testing { let mut frontier = BridgeFrontier::::empty(); for commitment in commitments.iter() { - let cmx = MerkleHashOrchard(pallas::Base::from_bytes(commitment).unwrap()); + let cmx = MerkleHashOrchard(pallas::Base::from_repr(*commitment).unwrap()); frontier.append(&cmx); } - assert_eq!( - frontier.root().0, - pallas::Base::from_bytes(&anchor).unwrap() - ); + assert_eq!(frontier.root().0, pallas::Base::from_repr(anchor).unwrap()); } } From b827298d428b061b7948f095076a00e518cac0d8 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 24 Nov 2021 16:48:04 +0000 Subject: [PATCH 48/59] poseidon: Rename `SpongeState` to `SpongeRate` --- src/circuit/gadget/poseidon.rs | 10 +++++----- src/circuit/gadget/poseidon/pow5.rs | 6 +++--- src/primitives/poseidon.rs | 24 ++++++++++++------------ 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/circuit/gadget/poseidon.rs b/src/circuit/gadget/poseidon.rs index 8bd109e5..135dfccb 100644 --- a/src/circuit/gadget/poseidon.rs +++ b/src/circuit/gadget/poseidon.rs @@ -13,7 +13,7 @@ use halo2::{ mod pow5; pub use pow5::{Pow5Chip, Pow5Config, StateWord}; -use crate::primitives::poseidon::{ConstantLength, Domain, Spec, Sponge, SpongeState, State}; +use crate::primitives::poseidon::{ConstantLength, Domain, Spec, Sponge, SpongeRate, State}; /// The set of circuit instructions required to use the Poseidon permutation. pub trait PoseidonInstructions, const T: usize, const RATE: usize>: @@ -53,11 +53,11 @@ pub trait PoseidonDuplexInstructions< layouter: &mut impl Layouter, domain: &impl Domain, initial_state: &State, - input: &SpongeState, + input: &SpongeRate, ) -> Result, Error>; /// Extracts sponge output from the given state. - fn get_output(state: &State) -> SpongeState; + fn get_output(state: &State) -> SpongeRate; } /// A word over which the Poseidon permutation operates. @@ -103,8 +103,8 @@ fn poseidon_duplex< mut layouter: impl Layouter, domain: &D, state: &mut State, - input: &SpongeState, -) -> Result, Error> { + input: &SpongeRate, +) -> Result, Error> { *state = chip.pad_and_add(&mut layouter, domain, state, input)?; *state = chip.permute(&mut layouter, state)?; Ok(PoseidonChip::get_output(state)) diff --git a/src/circuit/gadget/poseidon/pow5.rs b/src/circuit/gadget/poseidon/pow5.rs index de6d4aa6..0c509352 100644 --- a/src/circuit/gadget/poseidon/pow5.rs +++ b/src/circuit/gadget/poseidon/pow5.rs @@ -10,7 +10,7 @@ use halo2::{ use super::{PoseidonDuplexInstructions, PoseidonInstructions}; use crate::circuit::gadget::utilities::Var; -use crate::primitives::poseidon::{Domain, Mds, Spec, SpongeState, State}; +use crate::primitives::poseidon::{Domain, Mds, Spec, SpongeRate, State}; /// Configuration for a [`Pow5Chip`]. #[derive(Clone, Debug)] @@ -310,7 +310,7 @@ impl, const WIDTH: usize, const RATE: usize layouter: &mut impl Layouter, domain: &impl Domain, initial_state: &State, - input: &SpongeState, + input: &SpongeRate, ) -> Result, Error> { let config = self.config(); layouter.assign_region( @@ -386,7 +386,7 @@ impl, const WIDTH: usize, const RATE: usize ) } - fn get_output(state: &State) -> SpongeState { + fn get_output(state: &State) -> SpongeRate { state[..RATE] .iter() .map(|word| Some(word.clone())) diff --git a/src/primitives/poseidon.rs b/src/primitives/poseidon.rs index 1afe5cbe..df54d2c0 100644 --- a/src/primitives/poseidon.rs +++ b/src/primitives/poseidon.rs @@ -25,7 +25,7 @@ use grain::SboxType; pub(crate) type State = [F; T]; /// The type used to hold duplex sponge state. -pub(crate) type SpongeState = [Option; RATE]; +pub(crate) type SpongeRate = [Option; RATE]; /// The type used to hold the MDS matrix and its inverse. pub(crate) type Mds = [[F; T]; T]; @@ -126,11 +126,11 @@ pub(crate) fn permute, const T: usize, const RA fn poseidon_duplex, const T: usize, const RATE: usize>( state: &mut State, - input: &SpongeState, - pad_and_add: &dyn Fn(&mut State, &SpongeState), + input: &SpongeRate, + pad_and_add: &dyn Fn(&mut State, &SpongeRate), mds_matrix: &Mds, round_constants: &[[F; T]], -) -> SpongeState { +) -> SpongeRate { pad_and_add(state, input); permute::(state, mds_matrix, round_constants); @@ -144,8 +144,8 @@ fn poseidon_duplex, const T: usize, const RATE: #[derive(Debug)] pub(crate) enum Sponge { - Absorbing(SpongeState), - Squeezing(SpongeState), + Absorbing(SpongeRate), + Squeezing(SpongeRate), } impl Sponge { @@ -164,7 +164,7 @@ impl Sponge { pub(crate) struct Duplex, const T: usize, const RATE: usize> { sponge: Sponge, state: State, - pad_and_add: Box, &SpongeState)>, + pad_and_add: Box, &SpongeRate)>, mds_matrix: Mds, round_constants: Vec<[F; T]>, _marker: PhantomData, @@ -174,7 +174,7 @@ impl, const T: usize, const RATE: usize> Duplex /// Constructs a new duplex sponge for the given Poseidon specification. pub(crate) fn new( initial_capacity_element: F, - pad_and_add: Box, &SpongeState)>, + pad_and_add: Box, &SpongeRate)>, ) -> Self { let (round_constants, mds_matrix, _) = S::constants(); @@ -254,11 +254,11 @@ pub trait Domain: Copy + fmt::De fn initial_capacity_element(&self) -> F; /// The padding that will be added to each state word by [`Domain::pad_and_add`]. - fn padding(&self) -> SpongeState; + fn padding(&self) -> SpongeRate; /// Returns a function that will update the given state with the given input to a /// duplex permutation round, applying padding according to this domain specification. - fn pad_and_add(&self) -> Box, &SpongeState)>; + fn pad_and_add(&self) -> Box, &SpongeRate)>; } /// A Poseidon hash function used with constant input length. @@ -276,7 +276,7 @@ impl Domain SpongeState { + fn padding(&self) -> SpongeRate { // For constant-input-length hashing, padding consists of the field elements being // zero. let mut padding = [None; RATE]; @@ -286,7 +286,7 @@ impl Domain Box, &SpongeState)> { + fn pad_and_add(&self) -> Box, &SpongeRate)> { Box::new(|state, input| { // `Iterator::zip` short-circuits when one iterator completes, so this will only // mutate the rate portion of the state. From 9f654005c72daf1f6378276ebfb519eb7b0a9679 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 24 Nov 2021 17:01:33 +0000 Subject: [PATCH 49/59] poseidon: Replace the `Duplex` struct with a `Sponge` struct The `Sponge` struct's API correctly enforces the properties of a sponge: it can absorb an arbitrary number of elements, and then squeeze an arbitrary number of elements, but cannot absorb after it has squeezed. Co-authored-by: ying tong --- src/circuit/gadget/poseidon.rs | 157 +++++++++++++++----------- src/circuit/gadget/poseidon/pow5.rs | 4 +- src/primitives/poseidon.rs | 168 ++++++++++++++++------------ 3 files changed, 188 insertions(+), 141 deletions(-) diff --git a/src/circuit/gadget/poseidon.rs b/src/circuit/gadget/poseidon.rs index 135dfccb..771a6188 100644 --- a/src/circuit/gadget/poseidon.rs +++ b/src/circuit/gadget/poseidon.rs @@ -3,6 +3,7 @@ use std::array; use std::convert::TryInto; use std::fmt; +use std::marker::PhantomData; use halo2::{ arithmetic::FieldExt, @@ -13,7 +14,9 @@ use halo2::{ mod pow5; pub use pow5::{Pow5Chip, Pow5Config, StateWord}; -use crate::primitives::poseidon::{ConstantLength, Domain, Spec, Sponge, SpongeRate, State}; +use crate::primitives::poseidon::{ + Absorbing, ConstantLength, Domain, Spec, SpongeMode, SpongeRate, Squeezing, State, +}; /// The set of circuit instructions required to use the Poseidon permutation. pub trait PoseidonInstructions, const T: usize, const RATE: usize>: @@ -30,10 +33,10 @@ pub trait PoseidonInstructions, const T: usize, ) -> Result, Error>; } -/// The set of circuit instructions required to use the [`Duplex`] and [`Hash`] gadgets. +/// The set of circuit instructions required to use the [`Sponge`] and [`Hash`] gadgets. /// /// [`Hash`]: self::Hash -pub trait PoseidonDuplexInstructions< +pub trait PoseidonSpongeInstructions< F: FieldExt, S: Spec, const T: usize, @@ -91,9 +94,9 @@ impl< } } -fn poseidon_duplex< +fn poseidon_sponge< F: FieldExt, - PoseidonChip: PoseidonDuplexInstructions, + PoseidonChip: PoseidonSpongeInstructions, S: Spec, D: Domain, const T: usize, @@ -110,30 +113,32 @@ fn poseidon_duplex< Ok(PoseidonChip::get_output(state)) } -/// A Poseidon duplex sponge. +/// A Poseidon sponge. #[derive(Debug)] -pub struct Duplex< +pub struct Sponge< F: FieldExt, - PoseidonChip: PoseidonDuplexInstructions, + PoseidonChip: PoseidonSpongeInstructions, S: Spec, + M: SpongeMode, D: Domain, const T: usize, const RATE: usize, > { chip: PoseidonChip, - sponge: Sponge, + mode: M, state: State, domain: D, + _marker: PhantomData, } impl< F: FieldExt, - PoseidonChip: PoseidonDuplexInstructions, + PoseidonChip: PoseidonSpongeInstructions, S: Spec, D: Domain, const T: usize, const RATE: usize, - > Duplex + > Sponge, D, T, RATE> { /// Constructs a new duplex sponge for the given Poseidon specification. pub fn new( @@ -142,9 +147,9 @@ impl< domain: D, ) -> Result { chip.initial_state(&mut layouter, &domain) - .map(|state| Duplex { + .map(|state| Sponge { chip, - sponge: Sponge::Absorbing( + mode: Absorbing( (0..RATE) .map(|_| None) .collect::>() @@ -153,6 +158,7 @@ impl< ), state, domain, + _marker: PhantomData::default(), }) } @@ -162,84 +168,97 @@ impl< mut layouter: impl Layouter, value: AssignedCell, ) -> Result<(), Error> { - match self.sponge { - Sponge::Absorbing(ref mut input) => { - for entry in input.iter_mut() { - if entry.is_none() { - *entry = Some(value.into()); - return Ok(()); - } - } - - // We've already absorbed as many elements as we can - let _ = poseidon_duplex( - &self.chip, - layouter.namespace(|| "PoseidonDuplex"), - &self.domain, - &mut self.state, - input, - )?; - self.sponge = Sponge::absorb(value.into()); - } - Sponge::Squeezing(_) => { - // Drop the remaining output elements - self.sponge = Sponge::absorb(value.into()); + for entry in self.mode.0.iter_mut() { + if entry.is_none() { + *entry = Some(value.into()); + return Ok(()); } } + // We've already absorbed as many elements as we can + let _ = poseidon_sponge( + &self.chip, + layouter.namespace(|| "PoseidonSponge"), + &self.domain, + &mut self.state, + &self.mode.0, + )?; + self.mode = Absorbing::init_with(value.into()); + Ok(()) } + /// Transitions the sponge into its squeezing state. + #[allow(clippy::type_complexity)] + pub fn finish_absorbing( + mut self, + mut layouter: impl Layouter, + ) -> Result, D, T, RATE>, Error> + { + let mode = Squeezing(poseidon_sponge( + &self.chip, + layouter.namespace(|| "PoseidonSponge"), + &self.domain, + &mut self.state, + &self.mode.0, + )?); + + Ok(Sponge { + chip: self.chip, + mode, + state: self.state, + domain: self.domain, + _marker: PhantomData::default(), + }) + } +} + +impl< + F: FieldExt, + PoseidonChip: PoseidonSpongeInstructions, + S: Spec, + D: Domain, + const T: usize, + const RATE: usize, + > Sponge, D, T, RATE> +{ /// Squeezes an element from the sponge. pub fn squeeze(&mut self, mut layouter: impl Layouter) -> Result, Error> { loop { - match self.sponge { - Sponge::Absorbing(ref input) => { - self.sponge = Sponge::Squeezing(poseidon_duplex( - &self.chip, - layouter.namespace(|| "PoseidonDuplex"), - &self.domain, - &mut self.state, - input, - )?); - } - Sponge::Squeezing(ref mut output) => { - for entry in output.iter_mut() { - if let Some(inner) = entry.take() { - return Ok(inner.into()); - } - } - - // We've already squeezed out all available elements - self.sponge = Sponge::Absorbing( - (0..RATE) - .map(|_| None) - .collect::>() - .try_into() - .unwrap(), - ); + for entry in self.mode.0.iter_mut() { + if let Some(inner) = entry.take() { + return Ok(inner.into()); } } + + // We've already squeezed out all available elements + self.mode = Squeezing(poseidon_sponge( + &self.chip, + layouter.namespace(|| "PoseidonSponge"), + &self.domain, + &mut self.state, + &self.mode.0, + )?); } } } -/// A Poseidon hash function, built around a duplex sponge. +/// A Poseidon hash function, built around a sponge. #[derive(Debug)] pub struct Hash< F: FieldExt, - PoseidonChip: PoseidonDuplexInstructions, + PoseidonChip: PoseidonSpongeInstructions, S: Spec, D: Domain, const T: usize, const RATE: usize, > { - duplex: Duplex, + sponge: Sponge, D, T, RATE>, } impl< F: FieldExt, - PoseidonChip: PoseidonDuplexInstructions, + PoseidonChip: PoseidonSpongeInstructions, S: Spec, D: Domain, const T: usize, @@ -248,13 +267,13 @@ impl< { /// Initializes a new hasher. pub fn init(chip: PoseidonChip, layouter: impl Layouter, domain: D) -> Result { - Duplex::new(chip, layouter, domain).map(|duplex| Hash { duplex }) + Sponge::new(chip, layouter, domain).map(|sponge| Hash { sponge }) } } impl< F: FieldExt, - PoseidonChip: PoseidonDuplexInstructions, + PoseidonChip: PoseidonSpongeInstructions, S: Spec, const T: usize, const RATE: usize, @@ -268,9 +287,11 @@ impl< message: [AssignedCell; L], ) -> Result, Error> { for (i, value) in array::IntoIter::new(message).enumerate() { - self.duplex + self.sponge .absorb(layouter.namespace(|| format!("absorb_{}", i)), value)?; } - self.duplex.squeeze(layouter.namespace(|| "squeeze")) + self.sponge + .finish_absorbing(layouter.namespace(|| "finish absorbing"))? + .squeeze(layouter.namespace(|| "squeeze")) } } diff --git a/src/circuit/gadget/poseidon/pow5.rs b/src/circuit/gadget/poseidon/pow5.rs index 0c509352..1880e1af 100644 --- a/src/circuit/gadget/poseidon/pow5.rs +++ b/src/circuit/gadget/poseidon/pow5.rs @@ -8,7 +8,7 @@ use halo2::{ poly::Rotation, }; -use super::{PoseidonDuplexInstructions, PoseidonInstructions}; +use super::{PoseidonInstructions, PoseidonSpongeInstructions}; use crate::circuit::gadget::utilities::Var; use crate::primitives::poseidon::{Domain, Mds, Spec, SpongeRate, State}; @@ -269,7 +269,7 @@ impl, const WIDTH: usize, const RATE: usize } impl, const WIDTH: usize, const RATE: usize> - PoseidonDuplexInstructions for Pow5Chip + PoseidonSpongeInstructions for Pow5Chip { fn initial_state( &self, diff --git a/src/primitives/poseidon.rs b/src/primitives/poseidon.rs index df54d2c0..10933404 100644 --- a/src/primitives/poseidon.rs +++ b/src/primitives/poseidon.rs @@ -24,7 +24,7 @@ use grain::SboxType; /// The type used to hold permutation state. pub(crate) type State = [F; T]; -/// The type used to hold duplex sponge state. +/// The type used to hold sponge rate. pub(crate) type SpongeRate = [Option; RATE]; /// The type used to hold the MDS matrix and its inverse. @@ -124,7 +124,7 @@ pub(crate) fn permute, const T: usize, const RA }); } -fn poseidon_duplex, const T: usize, const RATE: usize>( +fn poseidon_sponge, const T: usize, const RATE: usize>( state: &mut State, input: &SpongeRate, pad_and_add: &dyn Fn(&mut State, &SpongeRate), @@ -142,48 +142,65 @@ fn poseidon_duplex, const T: usize, const RATE: output } -#[derive(Debug)] -pub(crate) enum Sponge { - Absorbing(SpongeRate), - Squeezing(SpongeRate), -} +/// The state of the [`Sponge`]. +// TODO: Seal this trait? +pub trait SpongeMode {} -impl Sponge { - pub(crate) fn absorb(val: F) -> Self { - let mut input: [Option; RATE] = (0..RATE) - .map(|_| None) - .collect::>() - .try_into() - .unwrap(); - input[0] = Some(val); - Sponge::Absorbing(input) +/// The absorbing state of the [`Sponge`]. +#[derive(Debug)] +pub struct Absorbing(pub(crate) SpongeRate); + +/// The squeezing state of the [`Sponge`]. +#[derive(Debug)] +pub struct Squeezing(pub(crate) SpongeRate); + +impl SpongeMode for Absorbing {} +impl SpongeMode for Squeezing {} + +impl Absorbing { + pub(crate) fn init_with(val: F) -> Self { + Self( + iter::once(Some(val)) + .chain((1..RATE).map(|_| None)) + .collect::>() + .try_into() + .unwrap(), + ) } } -/// A Poseidon duplex sponge. -pub(crate) struct Duplex, const T: usize, const RATE: usize> { - sponge: Sponge, +/// A Poseidon sponge. +pub(crate) struct Sponge< + F: FieldExt, + S: Spec, + M: SpongeMode, + const T: usize, + const RATE: usize, +> { + mode: M, state: State, pad_and_add: Box, &SpongeRate)>, mds_matrix: Mds, round_constants: Vec<[F; T]>, - _marker: PhantomData, + _marker: PhantomData<(S, M)>, } -impl, const T: usize, const RATE: usize> Duplex { - /// Constructs a new duplex sponge for the given Poseidon specification. +impl, const T: usize, const RATE: usize> + Sponge, T, RATE> +{ + /// Constructs a new sponge for the given Poseidon specification. pub(crate) fn new( initial_capacity_element: F, pad_and_add: Box, &SpongeRate)>, ) -> Self { let (round_constants, mds_matrix, _) = S::constants(); - let input = [None; RATE]; + let mode = Absorbing([None; RATE]); let mut state = [F::zero(); T]; state[RATE] = initial_capacity_element; - Duplex { - sponge: Sponge::Absorbing(input), + Sponge { + mode, state, pad_and_add, mds_matrix, @@ -194,56 +211,65 @@ impl, const T: usize, const RATE: usize> Duplex /// Absorbs an element into the sponge. pub(crate) fn absorb(&mut self, value: F) { - match self.sponge { - Sponge::Absorbing(ref mut input) => { - for entry in input.iter_mut() { - if entry.is_none() { - *entry = Some(value); - return; - } - } - - // We've already absorbed as many elements as we can - let _ = poseidon_duplex::( - &mut self.state, - input, - &self.pad_and_add, - &self.mds_matrix, - &self.round_constants, - ); - self.sponge = Sponge::absorb(value); - } - Sponge::Squeezing(_) => { - // Drop the remaining output elements - self.sponge = Sponge::absorb(value); + for entry in self.mode.0.iter_mut() { + if entry.is_none() { + *entry = Some(value); + return; } } + + // We've already absorbed as many elements as we can + let _ = poseidon_sponge::( + &mut self.state, + &self.mode.0, + &self.pad_and_add, + &self.mds_matrix, + &self.round_constants, + ); + self.mode = Absorbing::init_with(value); } + /// Transitions the sponge into its squeezing state. + pub(crate) fn finish_absorbing(mut self) -> Sponge, T, RATE> { + let mode = Squeezing(poseidon_sponge::( + &mut self.state, + &self.mode.0, + &self.pad_and_add, + &self.mds_matrix, + &self.round_constants, + )); + + Sponge { + mode, + state: self.state, + pad_and_add: self.pad_and_add, + mds_matrix: self.mds_matrix, + round_constants: self.round_constants, + _marker: PhantomData::default(), + } + } +} + +impl, const T: usize, const RATE: usize> + Sponge, T, RATE> +{ /// Squeezes an element from the sponge. pub(crate) fn squeeze(&mut self) -> F { loop { - match self.sponge { - Sponge::Absorbing(ref input) => { - self.sponge = Sponge::Squeezing(poseidon_duplex::( - &mut self.state, - input, - &self.pad_and_add, - &self.mds_matrix, - &self.round_constants, - )); - } - Sponge::Squeezing(ref mut output) => { - for entry in output.iter_mut() { - if let Some(e) = entry.take() { - return e; - } - } - - // We've already squeezed out all available elements - self.sponge = Sponge::Absorbing([None; RATE]); + for entry in self.mode.0.iter_mut() { + if let Some(e) = entry.take() { + return e; } } + + // We've already squeezed out all available elements + self.mode = Squeezing(poseidon_sponge::( + &mut self.state, + &self.mode.0, + &self.pad_and_add, + &self.mds_matrix, + &self.round_constants, + )); } } } @@ -301,7 +327,7 @@ impl Domain, @@ -309,7 +335,7 @@ pub struct Hash< const T: usize, const RATE: usize, > { - duplex: Duplex, + sponge: Sponge, T, RATE>, domain: D, } @@ -343,7 +369,7 @@ impl< /// Initializes a new hasher. pub fn init(domain: D) -> Self { Hash { - duplex: Duplex::new(domain.initial_capacity_element(), domain.pad_and_add()), + sponge: Sponge::new(domain.initial_capacity_element(), domain.pad_and_add()), domain, } } @@ -355,9 +381,9 @@ impl, const T: usize, const RATE: usize, const /// Hashes the given input. pub fn hash(mut self, message: [F; L]) -> F { for value in array::IntoIter::new(message) { - self.duplex.absorb(value); + self.sponge.absorb(value); } - self.duplex.squeeze() + self.sponge.finish_absorbing().squeeze() } } From bfc65d5985cdb6fddef38b34d7d1565ed9e032e6 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 9 Dec 2021 20:23:27 +0000 Subject: [PATCH 50/59] poseidon: Remove `self` parameter from `Domain` trait methods For almost all the sponge constructions defined in the Poseidon paper, the domain can be defined completely statically. Variable-length hashing requires knowledge of the message length, but that can be provided to the fixed padding function in a subsequent commit, and in any case we can't use variable-length inputs in a circuit. --- benches/poseidon.rs | 5 +- benches/primitives.rs | 4 +- src/circuit.rs | 10 ++-- src/circuit/gadget/poseidon.rs | 69 +++++++++++---------------- src/circuit/gadget/poseidon/pow5.rs | 28 ++++++----- src/primitives/poseidon.rs | 33 ++++++++----- src/primitives/poseidon/p128pow5t3.rs | 6 ++- src/spec.rs | 2 +- 8 files changed, 77 insertions(+), 80 deletions(-) diff --git a/benches/poseidon.rs b/benches/poseidon.rs index 480be0b9..1d585448 100644 --- a/benches/poseidon.rs +++ b/benches/poseidon.rs @@ -101,10 +101,9 @@ where }, )?; - let hasher = Hash::<_, _, S, _, WIDTH, RATE>::init( + let hasher = Hash::<_, _, S, ConstantLength, WIDTH, RATE>::init( chip, layouter.namespace(|| "init"), - ConstantLength::, )?; let output = hasher.hash(layouter.namespace(|| "hash"), message)?; @@ -210,7 +209,7 @@ fn bench_poseidon( .collect::>() .try_into() .unwrap(); - let output = poseidon::Hash::<_, S, _, WIDTH, RATE>::init(ConstantLength::).hash(message); + let output = poseidon::Hash::<_, S, ConstantLength, WIDTH, RATE>::init().hash(message); let circuit = HashCircuit:: { message: Some(message), diff --git a/benches/primitives.rs b/benches/primitives.rs index 4d141c69..e5cadd8a 100644 --- a/benches/primitives.rs +++ b/benches/primitives.rs @@ -21,7 +21,9 @@ fn bench_primitives(c: &mut Criterion) { let message = [pallas::Base::random(rng), pallas::Base::random(rng)]; group.bench_function("2-to-1", |b| { - b.iter(|| poseidon::Hash::<_, P128Pow5T3, _, 3, 2>::init(ConstantLength).hash(message)) + b.iter(|| { + poseidon::Hash::<_, P128Pow5T3, ConstantLength<2>, 3, 2>::init().hash(message) + }) }); } diff --git a/src/circuit.rs b/src/circuit.rs index 79899c10..bfdbf35b 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -482,11 +482,11 @@ impl plonk::Circuit for Circuit { // hash_old = poseidon_hash(nk, rho_old) let hash_old = { let poseidon_message = [nk.clone(), rho_old.clone()]; - let poseidon_hasher = PoseidonHash::<_, _, poseidon::P128Pow5T3, _, 3, 2>::init( - config.poseidon_chip(), - layouter.namespace(|| "Poseidon init"), - ConstantLength::<2>, - )?; + let poseidon_hasher = + PoseidonHash::<_, _, poseidon::P128Pow5T3, ConstantLength<2>, 3, 2>::init( + config.poseidon_chip(), + layouter.namespace(|| "Poseidon init"), + )?; poseidon_hasher.hash( layouter.namespace(|| "Poseidon hash (nk, rho_old)"), poseidon_message, diff --git a/src/circuit/gadget/poseidon.rs b/src/circuit/gadget/poseidon.rs index 771a6188..cdaaecaf 100644 --- a/src/circuit/gadget/poseidon.rs +++ b/src/circuit/gadget/poseidon.rs @@ -39,22 +39,19 @@ pub trait PoseidonInstructions, const T: usize, pub trait PoseidonSpongeInstructions< F: FieldExt, S: Spec, + D: Domain, const T: usize, const RATE: usize, >: PoseidonInstructions { /// Returns the initial empty state for the given domain. - fn initial_state( - &self, - layouter: &mut impl Layouter, - domain: &impl Domain, - ) -> Result, Error>; + fn initial_state(&self, layouter: &mut impl Layouter) + -> Result, Error>; /// Pads the given input (according to the specified domain) and adds it to the state. fn pad_and_add( &self, layouter: &mut impl Layouter, - domain: &impl Domain, initial_state: &State, input: &SpongeRate, ) -> Result, Error>; @@ -96,7 +93,7 @@ impl< fn poseidon_sponge< F: FieldExt, - PoseidonChip: PoseidonSpongeInstructions, + PoseidonChip: PoseidonSpongeInstructions, S: Spec, D: Domain, const T: usize, @@ -104,11 +101,10 @@ fn poseidon_sponge< >( chip: &PoseidonChip, mut layouter: impl Layouter, - domain: &D, state: &mut State, input: &SpongeRate, ) -> Result, Error> { - *state = chip.pad_and_add(&mut layouter, domain, state, input)?; + *state = chip.pad_and_add(&mut layouter, state, input)?; *state = chip.permute(&mut layouter, state)?; Ok(PoseidonChip::get_output(state)) } @@ -117,7 +113,7 @@ fn poseidon_sponge< #[derive(Debug)] pub struct Sponge< F: FieldExt, - PoseidonChip: PoseidonSpongeInstructions, + PoseidonChip: PoseidonSpongeInstructions, S: Spec, M: SpongeMode, D: Domain, @@ -127,13 +123,12 @@ pub struct Sponge< chip: PoseidonChip, mode: M, state: State, - domain: D, - _marker: PhantomData, + _marker: PhantomData<(M, D)>, } impl< F: FieldExt, - PoseidonChip: PoseidonSpongeInstructions, + PoseidonChip: PoseidonSpongeInstructions, S: Spec, D: Domain, const T: usize, @@ -141,25 +136,19 @@ impl< > Sponge, D, T, RATE> { /// Constructs a new duplex sponge for the given Poseidon specification. - pub fn new( - chip: PoseidonChip, - mut layouter: impl Layouter, - domain: D, - ) -> Result { - chip.initial_state(&mut layouter, &domain) - .map(|state| Sponge { - chip, - mode: Absorbing( - (0..RATE) - .map(|_| None) - .collect::>() - .try_into() - .unwrap(), - ), - state, - domain, - _marker: PhantomData::default(), - }) + pub fn new(chip: PoseidonChip, mut layouter: impl Layouter) -> Result { + chip.initial_state(&mut layouter).map(|state| Sponge { + chip, + mode: Absorbing( + (0..RATE) + .map(|_| None) + .collect::>() + .try_into() + .unwrap(), + ), + state, + _marker: PhantomData::default(), + }) } /// Absorbs an element into the sponge. @@ -179,7 +168,6 @@ impl< let _ = poseidon_sponge( &self.chip, layouter.namespace(|| "PoseidonSponge"), - &self.domain, &mut self.state, &self.mode.0, )?; @@ -198,7 +186,6 @@ impl< let mode = Squeezing(poseidon_sponge( &self.chip, layouter.namespace(|| "PoseidonSponge"), - &self.domain, &mut self.state, &self.mode.0, )?); @@ -207,7 +194,6 @@ impl< chip: self.chip, mode, state: self.state, - domain: self.domain, _marker: PhantomData::default(), }) } @@ -215,7 +201,7 @@ impl< impl< F: FieldExt, - PoseidonChip: PoseidonSpongeInstructions, + PoseidonChip: PoseidonSpongeInstructions, S: Spec, D: Domain, const T: usize, @@ -235,7 +221,6 @@ impl< self.mode = Squeezing(poseidon_sponge( &self.chip, layouter.namespace(|| "PoseidonSponge"), - &self.domain, &mut self.state, &self.mode.0, )?); @@ -247,7 +232,7 @@ impl< #[derive(Debug)] pub struct Hash< F: FieldExt, - PoseidonChip: PoseidonSpongeInstructions, + PoseidonChip: PoseidonSpongeInstructions, S: Spec, D: Domain, const T: usize, @@ -258,7 +243,7 @@ pub struct Hash< impl< F: FieldExt, - PoseidonChip: PoseidonSpongeInstructions, + PoseidonChip: PoseidonSpongeInstructions, S: Spec, D: Domain, const T: usize, @@ -266,14 +251,14 @@ impl< > Hash { /// Initializes a new hasher. - pub fn init(chip: PoseidonChip, layouter: impl Layouter, domain: D) -> Result { - Sponge::new(chip, layouter, domain).map(|sponge| Hash { sponge }) + pub fn init(chip: PoseidonChip, layouter: impl Layouter) -> Result { + Sponge::new(chip, layouter).map(|sponge| Hash { sponge }) } } impl< F: FieldExt, - PoseidonChip: PoseidonSpongeInstructions, + PoseidonChip: PoseidonSpongeInstructions, T, RATE>, S: Spec, const T: usize, const RATE: usize, diff --git a/src/circuit/gadget/poseidon/pow5.rs b/src/circuit/gadget/poseidon/pow5.rs index 1880e1af..f8ba67c4 100644 --- a/src/circuit/gadget/poseidon/pow5.rs +++ b/src/circuit/gadget/poseidon/pow5.rs @@ -268,17 +268,21 @@ impl, const WIDTH: usize, const RATE: usize } } -impl, const WIDTH: usize, const RATE: usize> - PoseidonSpongeInstructions for Pow5Chip +impl< + F: FieldExt, + S: Spec, + D: Domain, + const WIDTH: usize, + const RATE: usize, + > PoseidonSpongeInstructions for Pow5Chip { fn initial_state( &self, layouter: &mut impl Layouter, - domain: &impl Domain, ) -> Result, Error> { let config = self.config(); let state = layouter.assign_region( - || format!("initial state for domain {:?}", domain), + || format!("initial state for domain {}", D::name()), |mut region| { let mut state = Vec::with_capacity(WIDTH); let mut load_state_word = |i: usize, value: F| -> Result<_, Error> { @@ -296,7 +300,7 @@ impl, const WIDTH: usize, const RATE: usize for i in 0..RATE { load_state_word(i, F::zero())?; } - load_state_word(RATE, domain.initial_capacity_element())?; + load_state_word(RATE, D::initial_capacity_element())?; Ok(state) }, @@ -308,13 +312,12 @@ impl, const WIDTH: usize, const RATE: usize fn pad_and_add( &self, layouter: &mut impl Layouter, - domain: &impl Domain, initial_state: &State, input: &SpongeRate, ) -> Result, Error> { let config = self.config(); layouter.assign_region( - || format!("pad-and-add for domain {:?}", domain), + || format!("pad-and-add for domain {}", D::name()), |mut region| { config.s_pad_and_add.enable(&mut region, 1)?; @@ -334,7 +337,7 @@ impl, const WIDTH: usize, const RATE: usize (0..WIDTH).map(load_state_word).collect(); let initial_state = initial_state?; - let padding_values = domain.padding(); + let padding_values = D::padding(); // Load the input and padding into this region. let load_input_word = |i: usize| { @@ -783,10 +786,9 @@ mod tests { }, )?; - let hasher = Hash::<_, _, S, _, WIDTH, RATE>::init( + let hasher = Hash::<_, _, S, ConstantLength, WIDTH, RATE>::init( chip, layouter.namespace(|| "init"), - ConstantLength::, )?; let output = hasher.hash(layouter.namespace(|| "hash"), message)?; @@ -809,7 +811,7 @@ mod tests { fn poseidon_hash() { let message = [Fp::rand(), Fp::rand()]; let output = - poseidon::Hash::<_, OrchardNullifier, _, 3, 2>::init(ConstantLength::<2>).hash(message); + poseidon::Hash::<_, OrchardNullifier, ConstantLength<2>, 3, 2>::init().hash(message); let k = 6; let circuit = HashCircuit:: { @@ -828,8 +830,8 @@ mod tests { pallas::Base::from_repr(tv.input[0]).unwrap(), pallas::Base::from_repr(tv.input[1]).unwrap(), ]; - let output = - poseidon::Hash::<_, OrchardNullifier, _, 3, 2>::init(ConstantLength).hash(message); + let output = poseidon::Hash::<_, OrchardNullifier, ConstantLength<2>, 3, 2>::init() + .hash(message); let k = 6; let circuit = HashCircuit:: { diff --git a/src/primitives/poseidon.rs b/src/primitives/poseidon.rs index 10933404..bd9c0777 100644 --- a/src/primitives/poseidon.rs +++ b/src/primitives/poseidon.rs @@ -275,16 +275,19 @@ impl, const T: usize, const RATE: usize> } /// A domain in which a Poseidon hash function is being used. -pub trait Domain: Copy + fmt::Debug { +pub trait Domain { + /// The name of this domain, for debug formatting purposes. + fn name() -> String; + /// The initial capacity element, encoding this domain. - fn initial_capacity_element(&self) -> F; + fn initial_capacity_element() -> F; /// The padding that will be added to each state word by [`Domain::pad_and_add`]. - fn padding(&self) -> SpongeRate; + fn padding() -> SpongeRate; /// Returns a function that will update the given state with the given input to a /// duplex permutation round, applying padding according to this domain specification. - fn pad_and_add(&self) -> Box, &SpongeRate)>; + fn pad_and_add() -> Box, &SpongeRate)>; } /// A Poseidon hash function used with constant input length. @@ -296,13 +299,17 @@ pub struct ConstantLength; impl Domain for ConstantLength { - fn initial_capacity_element(&self) -> F { + fn name() -> String { + format!("ConstantLength<{}>", L) + } + + fn initial_capacity_element() -> F { // Capacity value is $length \cdot 2^64 + (o-1)$ where o is the output length. // We hard-code an output length of 1. F::from_u128((L as u128) << 64) } - fn padding(&self) -> SpongeRate { + fn padding() -> SpongeRate { // For constant-input-length hashing, padding consists of the field elements being // zero. let mut padding = [None; RATE]; @@ -312,7 +319,7 @@ impl Domain Box, &SpongeRate)> { + fn pad_and_add() -> Box, &SpongeRate)> { Box::new(|state, input| { // `Iterator::zip` short-circuits when one iterator completes, so this will only // mutate the rate portion of the state. @@ -336,7 +343,7 @@ pub struct Hash< const RATE: usize, > { sponge: Sponge, T, RATE>, - domain: D, + _domain: PhantomData, } impl< @@ -353,7 +360,7 @@ impl< .field("rate", &RATE) .field("R_F", &S::full_rounds()) .field("R_P", &S::partial_rounds()) - .field("domain", &self.domain) + .field("domain", &D::name()) .finish() } } @@ -367,10 +374,10 @@ impl< > Hash { /// Initializes a new hasher. - pub fn init(domain: D) -> Self { + pub fn init() -> Self { Hash { - sponge: Sponge::new(domain.initial_capacity_element(), domain.pad_and_add()), - domain, + sponge: Sponge::new(D::initial_capacity_element(), D::pad_and_add()), + _domain: PhantomData::default(), } } } @@ -400,7 +407,7 @@ mod tests { let (round_constants, mds, _) = OrchardNullifier::constants(); - let hasher = Hash::<_, OrchardNullifier, _, 3, 2>::init(ConstantLength); + let hasher = Hash::<_, OrchardNullifier, ConstantLength<2>, 3, 2>::init(); let result = hasher.hash(message); // The result should be equivalent to just directly applying the permutation and diff --git a/src/primitives/poseidon/p128pow5t3.rs b/src/primitives/poseidon/p128pow5t3.rs index c33a9ca6..5052613d 100644 --- a/src/primitives/poseidon/p128pow5t3.rs +++ b/src/primitives/poseidon/p128pow5t3.rs @@ -292,7 +292,8 @@ mod tests { Fp::from_repr(tv.input[1]).unwrap(), ]; - let result = Hash::<_, super::P128Pow5T3, _, 3, 2>::init(ConstantLength).hash(message); + let result = + Hash::<_, super::P128Pow5T3, ConstantLength<2>, 3, 2>::init().hash(message); assert_eq!(result.to_repr(), tv.output); } @@ -303,7 +304,8 @@ mod tests { Fq::from_repr(tv.input[1]).unwrap(), ]; - let result = Hash::<_, super::P128Pow5T3, _, 3, 2>::init(ConstantLength).hash(message); + let result = + Hash::<_, super::P128Pow5T3, ConstantLength<2>, 3, 2>::init().hash(message); assert_eq!(result.to_repr(), tv.output); } diff --git a/src/spec.rs b/src/spec.rs index 7d1cd698..a5ba1200 100644 --- a/src/spec.rs +++ b/src/spec.rs @@ -212,7 +212,7 @@ pub(crate) fn diversify_hash(d: &[u8; 11]) -> NonIdentityPallasPoint { /// /// [concreteprfs]: https://zips.z.cash/protocol/nu5.pdf#concreteprfs pub(crate) fn prf_nf(nk: pallas::Base, rho: pallas::Base) -> pallas::Base { - poseidon::Hash::<_, poseidon::P128Pow5T3, _, 3, 2>::init(poseidon::ConstantLength) + poseidon::Hash::<_, poseidon::P128Pow5T3, poseidon::ConstantLength<2>, 3, 2>::init() .hash([nk, rho]) } From fdeb2fb81736a0d7c46c149cdf6ed57038a33007 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 10 Dec 2021 02:04:16 +0000 Subject: [PATCH 51/59] poseidon: Add circuit test case that fails This exposes a bug in the way padding was being handled by the invalid sponge-duplex hybrid construction. --- src/circuit/gadget/poseidon/pow5.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/circuit/gadget/poseidon/pow5.rs b/src/circuit/gadget/poseidon/pow5.rs index f8ba67c4..639a4545 100644 --- a/src/circuit/gadget/poseidon/pow5.rs +++ b/src/circuit/gadget/poseidon/pow5.rs @@ -823,6 +823,22 @@ mod tests { assert_eq!(prover.verify(), Ok(())) } + #[test] + fn poseidon_hash_longer_input() { + let message = [Fp::rand(), Fp::rand(), Fp::rand()]; + let output = + poseidon::Hash::<_, OrchardNullifier, ConstantLength<3>, 3, 2>::init().hash(message); + + let k = 7; + let circuit = HashCircuit:: { + message: Some(message), + output: Some(output), + _spec: PhantomData, + }; + let prover = MockProver::run(k, &circuit, vec![]).unwrap(); + assert_eq!(prover.verify(), Ok(())) + } + #[test] fn hash_test_vectors() { for tv in crate::primitives::poseidon::test_vectors::fp::hash() { From ae72813f776e87726e995c5df7532ef5c2a82d1d Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 10 Dec 2021 02:07:34 +0000 Subject: [PATCH 52/59] poseidon: Fix padding to follow sponge construction Sponge constructions pad the entire input message and then split it into rate-sized chunks. The previous implementation was using an incorrect duplex-like hybrid where padding was applied to each chunked input. We now use an enum to distinguish message and padding words being absorbed into the sponge. This also fixes two previous bugs: - If a `ConstantLength` hash had a length greater than the permutation's rate but not a multiple of it, no padding would be generated and the circuit would fail to create proofs. - If a sponge usage required more output than the permutation's rate, the squeeze-side permutations would in some cases incorrectly apply padding, when it should instead use the prior state as-is. We now add zeroes instead. This change doesn't alter the Orchard circuit, because it doesn't need any padding cells, only takes a single field element as output, and padding is still assigned in the same region as before. --- src/circuit/gadget/poseidon.rs | 56 +++++++++++------ src/circuit/gadget/poseidon/pow5.rs | 22 ++++--- src/primitives/poseidon.rs | 93 ++++++++++------------------- 3 files changed, 79 insertions(+), 92 deletions(-) diff --git a/src/circuit/gadget/poseidon.rs b/src/circuit/gadget/poseidon.rs index cdaaecaf..aff0c2c5 100644 --- a/src/circuit/gadget/poseidon.rs +++ b/src/circuit/gadget/poseidon.rs @@ -5,6 +5,7 @@ use std::convert::TryInto; use std::fmt; use std::marker::PhantomData; +use group::ff::Field; use halo2::{ arithmetic::FieldExt, circuit::{AssignedCell, Chip, Layouter}, @@ -18,6 +19,15 @@ use crate::primitives::poseidon::{ Absorbing, ConstantLength, Domain, Spec, SpongeMode, SpongeRate, Squeezing, State, }; +/// A word from the padded input to a Poseidon sponge. +#[derive(Clone, Debug)] +pub enum PaddedWord { + /// A message word provided by the prover. + Message(AssignedCell), + /// A padding word, that will be fixed in the circuit parameters. + Padding(F), +} + /// The set of circuit instructions required to use the Poseidon permutation. pub trait PoseidonInstructions, const T: usize, const RATE: usize>: Chip @@ -39,7 +49,7 @@ pub trait PoseidonInstructions, const T: usize, pub trait PoseidonSpongeInstructions< F: FieldExt, S: Spec, - D: Domain, + D: Domain, const T: usize, const RATE: usize, >: PoseidonInstructions @@ -48,12 +58,12 @@ pub trait PoseidonSpongeInstructions< fn initial_state(&self, layouter: &mut impl Layouter) -> Result, Error>; - /// Pads the given input (according to the specified domain) and adds it to the state. - fn pad_and_add( + /// Adds the given input to the state. + fn add_input( &self, layouter: &mut impl Layouter, initial_state: &State, - input: &SpongeRate, + input: &SpongeRate, RATE>, ) -> Result, Error>; /// Extracts sponge output from the given state. @@ -95,16 +105,16 @@ fn poseidon_sponge< F: FieldExt, PoseidonChip: PoseidonSpongeInstructions, S: Spec, - D: Domain, + D: Domain, const T: usize, const RATE: usize, >( chip: &PoseidonChip, mut layouter: impl Layouter, state: &mut State, - input: &SpongeRate, + input: &SpongeRate, RATE>, ) -> Result, Error> { - *state = chip.pad_and_add(&mut layouter, state, input)?; + *state = chip.add_input(&mut layouter, state, input)?; *state = chip.permute(&mut layouter, state)?; Ok(PoseidonChip::get_output(state)) } @@ -116,7 +126,7 @@ pub struct Sponge< PoseidonChip: PoseidonSpongeInstructions, S: Spec, M: SpongeMode, - D: Domain, + D: Domain, const T: usize, const RATE: usize, > { @@ -130,10 +140,10 @@ impl< F: FieldExt, PoseidonChip: PoseidonSpongeInstructions, S: Spec, - D: Domain, + D: Domain, const T: usize, const RATE: usize, - > Sponge, D, T, RATE> + > Sponge, RATE>, D, T, RATE> { /// Constructs a new duplex sponge for the given Poseidon specification. pub fn new(chip: PoseidonChip, mut layouter: impl Layouter) -> Result { @@ -155,11 +165,11 @@ impl< pub fn absorb( &mut self, mut layouter: impl Layouter, - value: AssignedCell, + value: PaddedWord, ) -> Result<(), Error> { for entry in self.mode.0.iter_mut() { if entry.is_none() { - *entry = Some(value.into()); + *entry = Some(value); return Ok(()); } } @@ -171,7 +181,7 @@ impl< &mut self.state, &self.mode.0, )?; - self.mode = Absorbing::init_with(value.into()); + self.mode = Absorbing::init_with(value); Ok(()) } @@ -203,7 +213,7 @@ impl< F: FieldExt, PoseidonChip: PoseidonSpongeInstructions, S: Spec, - D: Domain, + D: Domain, const T: usize, const RATE: usize, > Sponge, D, T, RATE> @@ -222,7 +232,11 @@ impl< &self.chip, layouter.namespace(|| "PoseidonSponge"), &mut self.state, - &self.mode.0, + &(0..RATE) + .map(|_| Some(PaddedWord::Padding(F::zero()))) + .collect::>() + .try_into() + .unwrap(), )?); } } @@ -234,18 +248,18 @@ pub struct Hash< F: FieldExt, PoseidonChip: PoseidonSpongeInstructions, S: Spec, - D: Domain, + D: Domain, const T: usize, const RATE: usize, > { - sponge: Sponge, D, T, RATE>, + sponge: Sponge, RATE>, D, T, RATE>, } impl< F: FieldExt, PoseidonChip: PoseidonSpongeInstructions, S: Spec, - D: Domain, + D: Domain, const T: usize, const RATE: usize, > Hash @@ -271,7 +285,11 @@ impl< mut layouter: impl Layouter, message: [AssignedCell; L], ) -> Result, Error> { - for (i, value) in array::IntoIter::new(message).enumerate() { + for (i, value) in array::IntoIter::new(message) + .map(PaddedWord::Message) + .chain( as Domain>::padding(L).map(PaddedWord::Padding)) + .enumerate() + { self.sponge .absorb(layouter.namespace(|| format!("absorb_{}", i)), value)?; } diff --git a/src/circuit/gadget/poseidon/pow5.rs b/src/circuit/gadget/poseidon/pow5.rs index 639a4545..f6c5b865 100644 --- a/src/circuit/gadget/poseidon/pow5.rs +++ b/src/circuit/gadget/poseidon/pow5.rs @@ -8,7 +8,7 @@ use halo2::{ poly::Rotation, }; -use super::{PoseidonInstructions, PoseidonSpongeInstructions}; +use super::{PaddedWord, PoseidonInstructions, PoseidonSpongeInstructions}; use crate::circuit::gadget::utilities::Var; use crate::primitives::poseidon::{Domain, Mds, Spec, SpongeRate, State}; @@ -271,7 +271,7 @@ impl, const WIDTH: usize, const RATE: usize impl< F: FieldExt, S: Spec, - D: Domain, + D: Domain, const WIDTH: usize, const RATE: usize, > PoseidonSpongeInstructions for Pow5Chip @@ -309,15 +309,15 @@ impl< Ok(state.try_into().unwrap()) } - fn pad_and_add( + fn add_input( &self, layouter: &mut impl Layouter, initial_state: &State, - input: &SpongeRate, + input: &SpongeRate, RATE>, ) -> Result, Error> { let config = self.config(); layouter.assign_region( - || format!("pad-and-add for domain {}", D::name()), + || format!("add input for domain {}", D::name()), |mut region| { config.s_pad_and_add.enable(&mut region, 1)?; @@ -337,19 +337,17 @@ impl< (0..WIDTH).map(load_state_word).collect(); let initial_state = initial_state?; - let padding_values = D::padding(); - - // Load the input and padding into this region. + // Load the input into this region. let load_input_word = |i: usize| { - let constraint_var = match (input[i].clone(), padding_values[i]) { - (Some(word), None) => word.0, - (None, Some(padding_value)) => region.assign_fixed( + let constraint_var = match input[i].clone() { + Some(PaddedWord::Message(word)) => word, + Some(PaddedWord::Padding(padding_value)) => region.assign_fixed( || format!("load pad_{}", i), config.rc_b[i], 1, || Ok(padding_value), )?, - _ => panic!("Input and padding don't match"), + _ => panic!("Input is not padded"), }; constraint_var .copy_advice( diff --git a/src/primitives/poseidon.rs b/src/primitives/poseidon.rs index bd9c0777..87dff7c1 100644 --- a/src/primitives/poseidon.rs +++ b/src/primitives/poseidon.rs @@ -127,11 +127,14 @@ pub(crate) fn permute, const T: usize, const RA fn poseidon_sponge, const T: usize, const RATE: usize>( state: &mut State, input: &SpongeRate, - pad_and_add: &dyn Fn(&mut State, &SpongeRate), mds_matrix: &Mds, round_constants: &[[F; T]], ) -> SpongeRate { - pad_and_add(state, input); + // `Iterator::zip` short-circuits when one iterator completes, so this will only + // mutate the rate portion of the state. + for (word, value) in state.iter_mut().zip(input.iter()) { + *word += value.expect("poseidon_sponge is called with a padded input"); + } permute::(state, mds_matrix, round_constants); @@ -179,7 +182,6 @@ pub(crate) struct Sponge< > { mode: M, state: State, - pad_and_add: Box, &SpongeRate)>, mds_matrix: Mds, round_constants: Vec<[F; T]>, _marker: PhantomData<(S, M)>, @@ -189,10 +191,7 @@ impl, const T: usize, const RATE: usize> Sponge, T, RATE> { /// Constructs a new sponge for the given Poseidon specification. - pub(crate) fn new( - initial_capacity_element: F, - pad_and_add: Box, &SpongeRate)>, - ) -> Self { + pub(crate) fn new(initial_capacity_element: F) -> Self { let (round_constants, mds_matrix, _) = S::constants(); let mode = Absorbing([None; RATE]); @@ -202,7 +201,6 @@ impl, const T: usize, const RATE: usize> Sponge { mode, state, - pad_and_add, mds_matrix, round_constants, _marker: PhantomData::default(), @@ -222,7 +220,6 @@ impl, const T: usize, const RATE: usize> let _ = poseidon_sponge::( &mut self.state, &self.mode.0, - &self.pad_and_add, &self.mds_matrix, &self.round_constants, ); @@ -234,7 +231,6 @@ impl, const T: usize, const RATE: usize> let mode = Squeezing(poseidon_sponge::( &mut self.state, &self.mode.0, - &self.pad_and_add, &self.mds_matrix, &self.round_constants, )); @@ -242,7 +238,6 @@ impl, const T: usize, const RATE: usize> Sponge { mode, state: self.state, - pad_and_add: self.pad_and_add, mds_matrix: self.mds_matrix, round_constants: self.round_constants, _marker: PhantomData::default(), @@ -266,7 +261,6 @@ impl, const T: usize, const RATE: usize> self.mode = Squeezing(poseidon_sponge::( &mut self.state, &self.mode.0, - &self.pad_and_add, &self.mds_matrix, &self.round_constants, )); @@ -275,19 +269,18 @@ impl, const T: usize, const RATE: usize> } /// A domain in which a Poseidon hash function is being used. -pub trait Domain { +pub trait Domain { + /// Iterator that outputs padding field elements. + type Padding: IntoIterator; + /// The name of this domain, for debug formatting purposes. fn name() -> String; /// The initial capacity element, encoding this domain. fn initial_capacity_element() -> F; - /// The padding that will be added to each state word by [`Domain::pad_and_add`]. - fn padding() -> SpongeRate; - - /// Returns a function that will update the given state with the given input to a - /// duplex permutation round, applying padding according to this domain specification. - fn pad_and_add() -> Box, &SpongeRate)>; + /// Returns the padding to be appended to the input. + fn padding(input_len: usize) -> Self::Padding; } /// A Poseidon hash function used with constant input length. @@ -296,9 +289,9 @@ pub trait Domain { #[derive(Clone, Copy, Debug)] pub struct ConstantLength; -impl Domain - for ConstantLength -{ +impl Domain for ConstantLength { + type Padding = iter::Take>; + fn name() -> String { format!("ConstantLength<{}>", L) } @@ -309,28 +302,14 @@ impl Domain SpongeRate { - // For constant-input-length hashing, padding consists of the field elements being - // zero. - let mut padding = [None; RATE]; - for word in padding.iter_mut().skip(L) { - *word = Some(F::zero()); - } - padding - } - - fn pad_and_add() -> Box, &SpongeRate)> { - Box::new(|state, input| { - // `Iterator::zip` short-circuits when one iterator completes, so this will only - // mutate the rate portion of the state. - for (word, value) in state.iter_mut().zip(input.iter()) { - // For constant-input-length hashing, padding consists of the field - // elements being zero, so we don't add anything to the state. - if let Some(value) = value { - *word += value; - } - } - }) + fn padding(input_len: usize) -> Self::Padding { + assert_eq!(input_len, L); + // For constant-input-length hashing, we pad the input with zeroes to a multiple + // of RATE. On its own this is not sponge-compliant padding, but the Poseidon + // authors instead encode the constant length into the capacity element, ensuring + // that inputs of different lengths do not share the same permutation. + let k = (L + RATE - 1) / RATE; + iter::repeat(F::zero()).take(k * RATE - L) } } @@ -338,7 +317,7 @@ impl Domain, - D: Domain, + D: Domain, const T: usize, const RATE: usize, > { @@ -346,13 +325,8 @@ pub struct Hash< _domain: PhantomData, } -impl< - F: FieldExt, - S: Spec, - D: Domain, - const T: usize, - const RATE: usize, - > fmt::Debug for Hash +impl, D: Domain, const T: usize, const RATE: usize> + fmt::Debug for Hash { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Hash") @@ -365,18 +339,13 @@ impl< } } -impl< - F: FieldExt, - S: Spec, - D: Domain, - const T: usize, - const RATE: usize, - > Hash +impl, D: Domain, const T: usize, const RATE: usize> + Hash { /// Initializes a new hasher. pub fn init() -> Self { Hash { - sponge: Sponge::new(D::initial_capacity_element(), D::pad_and_add()), + sponge: Sponge::new(D::initial_capacity_element()), _domain: PhantomData::default(), } } @@ -387,7 +356,9 @@ impl, const T: usize, const RATE: usize, const { /// Hashes the given input. pub fn hash(mut self, message: [F; L]) -> F { - for value in array::IntoIter::new(message) { + for value in + array::IntoIter::new(message).chain( as Domain>::padding(L)) + { self.sponge.absorb(value); } self.sponge.finish_absorbing().squeeze() From 423006b905b208c034091c086ebbc5093af874d6 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 10 Dec 2021 02:25:09 +0000 Subject: [PATCH 53/59] poseidon: Remove redundant additions when squeezing sponge In the previous commit, we fixed a bug where padding was being added to the state when the sponge was in squeezing mode. But there's no need to assign a circuit region in which we add constant zeroes to the state :) --- src/circuit/gadget/poseidon.rs | 32 ++++++++++++++--------------- src/circuit/gadget/poseidon/pow5.rs | 27 ++++++++++++++---------- src/primitives/poseidon.rs | 30 ++++++++++++++------------- 3 files changed, 47 insertions(+), 42 deletions(-) diff --git a/src/circuit/gadget/poseidon.rs b/src/circuit/gadget/poseidon.rs index aff0c2c5..d851aacf 100644 --- a/src/circuit/gadget/poseidon.rs +++ b/src/circuit/gadget/poseidon.rs @@ -16,7 +16,7 @@ mod pow5; pub use pow5::{Pow5Chip, Pow5Config, StateWord}; use crate::primitives::poseidon::{ - Absorbing, ConstantLength, Domain, Spec, SpongeMode, SpongeRate, Squeezing, State, + Absorbing, ConstantLength, Domain, Spec, SpongeMode, Squeezing, State, }; /// A word from the padded input to a Poseidon sponge. @@ -63,11 +63,11 @@ pub trait PoseidonSpongeInstructions< &self, layouter: &mut impl Layouter, initial_state: &State, - input: &SpongeRate, RATE>, + input: &Absorbing, RATE>, ) -> Result, Error>; /// Extracts sponge output from the given state. - fn get_output(state: &State) -> SpongeRate; + fn get_output(state: &State) -> Squeezing; } /// A word over which the Poseidon permutation operates. @@ -112,9 +112,11 @@ fn poseidon_sponge< chip: &PoseidonChip, mut layouter: impl Layouter, state: &mut State, - input: &SpongeRate, RATE>, -) -> Result, Error> { - *state = chip.add_input(&mut layouter, state, input)?; + input: Option<&Absorbing, RATE>>, +) -> Result, Error> { + if let Some(input) = input { + *state = chip.add_input(&mut layouter, state, input)?; + } *state = chip.permute(&mut layouter, state)?; Ok(PoseidonChip::get_output(state)) } @@ -179,7 +181,7 @@ impl< &self.chip, layouter.namespace(|| "PoseidonSponge"), &mut self.state, - &self.mode.0, + Some(&self.mode), )?; self.mode = Absorbing::init_with(value); @@ -193,12 +195,12 @@ impl< mut layouter: impl Layouter, ) -> Result, D, T, RATE>, Error> { - let mode = Squeezing(poseidon_sponge( + let mode = poseidon_sponge( &self.chip, layouter.namespace(|| "PoseidonSponge"), &mut self.state, - &self.mode.0, - )?); + Some(&self.mode), + )?; Ok(Sponge { chip: self.chip, @@ -228,16 +230,12 @@ impl< } // We've already squeezed out all available elements - self.mode = Squeezing(poseidon_sponge( + self.mode = poseidon_sponge( &self.chip, layouter.namespace(|| "PoseidonSponge"), &mut self.state, - &(0..RATE) - .map(|_| Some(PaddedWord::Padding(F::zero()))) - .collect::>() - .try_into() - .unwrap(), - )?); + None, + )?; } } } diff --git a/src/circuit/gadget/poseidon/pow5.rs b/src/circuit/gadget/poseidon/pow5.rs index f6c5b865..9a74a8ac 100644 --- a/src/circuit/gadget/poseidon/pow5.rs +++ b/src/circuit/gadget/poseidon/pow5.rs @@ -9,8 +9,11 @@ use halo2::{ }; use super::{PaddedWord, PoseidonInstructions, PoseidonSpongeInstructions}; -use crate::circuit::gadget::utilities::Var; -use crate::primitives::poseidon::{Domain, Mds, Spec, SpongeRate, State}; +use crate::primitives::poseidon::{Domain, Mds, Spec, State}; +use crate::{ + circuit::gadget::utilities::Var, + primitives::poseidon::{Absorbing, Squeezing}, +}; /// Configuration for a [`Pow5Chip`]. #[derive(Clone, Debug)] @@ -313,7 +316,7 @@ impl< &self, layouter: &mut impl Layouter, initial_state: &State, - input: &SpongeRate, RATE>, + input: &Absorbing, RATE>, ) -> Result, Error> { let config = self.config(); layouter.assign_region( @@ -339,7 +342,7 @@ impl< // Load the input into this region. let load_input_word = |i: usize| { - let constraint_var = match input[i].clone() { + let constraint_var = match input.0[i].clone() { Some(PaddedWord::Message(word)) => word, Some(PaddedWord::Padding(padding_value)) => region.assign_fixed( || format!("load pad_{}", i), @@ -387,13 +390,15 @@ impl< ) } - fn get_output(state: &State) -> SpongeRate { - state[..RATE] - .iter() - .map(|word| Some(word.clone())) - .collect::>() - .try_into() - .unwrap() + fn get_output(state: &State) -> Squeezing { + Squeezing( + state[..RATE] + .iter() + .map(|word| Some(word.clone())) + .collect::>() + .try_into() + .unwrap(), + ) } } diff --git a/src/primitives/poseidon.rs b/src/primitives/poseidon.rs index 87dff7c1..34eb3c8c 100644 --- a/src/primitives/poseidon.rs +++ b/src/primitives/poseidon.rs @@ -126,14 +126,16 @@ pub(crate) fn permute, const T: usize, const RA fn poseidon_sponge, const T: usize, const RATE: usize>( state: &mut State, - input: &SpongeRate, + input: Option<&Absorbing>, mds_matrix: &Mds, round_constants: &[[F; T]], -) -> SpongeRate { - // `Iterator::zip` short-circuits when one iterator completes, so this will only - // mutate the rate portion of the state. - for (word, value) in state.iter_mut().zip(input.iter()) { - *word += value.expect("poseidon_sponge is called with a padded input"); +) -> Squeezing { + if let Some(Absorbing(input)) = input { + // `Iterator::zip` short-circuits when one iterator completes, so this will only + // mutate the rate portion of the state. + for (word, value) in state.iter_mut().zip(input.iter()) { + *word += value.expect("poseidon_sponge is called with a padded input"); + } } permute::(state, mds_matrix, round_constants); @@ -142,7 +144,7 @@ fn poseidon_sponge, const T: usize, const RATE: for (word, value) in output.iter_mut().zip(state.iter()) { *word = Some(*value); } - output + Squeezing(output) } /// The state of the [`Sponge`]. @@ -219,7 +221,7 @@ impl, const T: usize, const RATE: usize> // We've already absorbed as many elements as we can let _ = poseidon_sponge::( &mut self.state, - &self.mode.0, + Some(&self.mode), &self.mds_matrix, &self.round_constants, ); @@ -228,12 +230,12 @@ impl, const T: usize, const RATE: usize> /// Transitions the sponge into its squeezing state. pub(crate) fn finish_absorbing(mut self) -> Sponge, T, RATE> { - let mode = Squeezing(poseidon_sponge::( + let mode = poseidon_sponge::( &mut self.state, - &self.mode.0, + Some(&self.mode), &self.mds_matrix, &self.round_constants, - )); + ); Sponge { mode, @@ -258,12 +260,12 @@ impl, const T: usize, const RATE: usize> } // We've already squeezed out all available elements - self.mode = Squeezing(poseidon_sponge::( + self.mode = poseidon_sponge::( &mut self.state, - &self.mode.0, + None, &self.mds_matrix, &self.round_constants, - )); + ); } } } From a64e2d64a84665e6d92d23ae7fa6bb448511ff58 Mon Sep 17 00:00:00 2001 From: str4d Date: Wed, 15 Dec 2021 13:01:53 +0000 Subject: [PATCH 54/59] poseidon: Remove `M: SpongeMode` from `PhantomData` `M` was at one point only used as a type marker, but now it stores per-mode state. Co-authored-by: ying tong --- src/circuit/gadget/poseidon.rs | 2 +- src/primitives/poseidon.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/circuit/gadget/poseidon.rs b/src/circuit/gadget/poseidon.rs index d851aacf..92c8f409 100644 --- a/src/circuit/gadget/poseidon.rs +++ b/src/circuit/gadget/poseidon.rs @@ -135,7 +135,7 @@ pub struct Sponge< chip: PoseidonChip, mode: M, state: State, - _marker: PhantomData<(M, D)>, + _marker: PhantomData, } impl< diff --git a/src/primitives/poseidon.rs b/src/primitives/poseidon.rs index 34eb3c8c..ecbc07ef 100644 --- a/src/primitives/poseidon.rs +++ b/src/primitives/poseidon.rs @@ -186,7 +186,7 @@ pub(crate) struct Sponge< state: State, mds_matrix: Mds, round_constants: Vec<[F; T]>, - _marker: PhantomData<(S, M)>, + _marker: PhantomData, } impl, const T: usize, const RATE: usize> From 5948a4977a9acb93f338685c623fc8a44b9275d8 Mon Sep 17 00:00:00 2001 From: str4d Date: Wed, 15 Dec 2021 13:04:54 +0000 Subject: [PATCH 55/59] poseidon: Update code comments Also fixes some clippy lints (public docs linking to private items). Co-authored-by: Daira Hopwood --- src/primitives/poseidon.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/primitives/poseidon.rs b/src/primitives/poseidon.rs index ecbc07ef..7743fa56 100644 --- a/src/primitives/poseidon.rs +++ b/src/primitives/poseidon.rs @@ -147,15 +147,15 @@ fn poseidon_sponge, const T: usize, const RATE: Squeezing(output) } -/// The state of the [`Sponge`]. +/// The state of the `Sponge`. // TODO: Seal this trait? pub trait SpongeMode {} -/// The absorbing state of the [`Sponge`]. +/// The absorbing state of the `Sponge`. #[derive(Debug)] pub struct Absorbing(pub(crate) SpongeRate); -/// The squeezing state of the [`Sponge`]. +/// The squeezing state of the `Sponge`. #[derive(Debug)] pub struct Squeezing(pub(crate) SpongeRate); @@ -307,8 +307,8 @@ impl Domain for Constan fn padding(input_len: usize) -> Self::Padding { assert_eq!(input_len, L); // For constant-input-length hashing, we pad the input with zeroes to a multiple - // of RATE. On its own this is not sponge-compliant padding, but the Poseidon - // authors instead encode the constant length into the capacity element, ensuring + // of RATE. On its own this would not be sponge-compliant padding, but the + // Poseidon authors encode the constant length into the capacity element, ensuring // that inputs of different lengths do not share the same permutation. let k = (L + RATE - 1) / RATE; iter::repeat(F::zero()).take(k * RATE - L) From 8fe178e4339c41d0be51006e70d32a9b29c25daf Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 15 Dec 2021 13:08:08 +0000 Subject: [PATCH 56/59] poseidon: Seal the sponge modes A sponge can only have two modes: absorbing, and squeezing. --- src/primitives/poseidon.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/primitives/poseidon.rs b/src/primitives/poseidon.rs index 7743fa56..9c54841e 100644 --- a/src/primitives/poseidon.rs +++ b/src/primitives/poseidon.rs @@ -147,9 +147,14 @@ fn poseidon_sponge, const T: usize, const RATE: Squeezing(output) } +mod private { + pub trait SealedSpongeMode {} + impl SealedSpongeMode for super::Absorbing {} + impl SealedSpongeMode for super::Squeezing {} +} + /// The state of the `Sponge`. -// TODO: Seal this trait? -pub trait SpongeMode {} +pub trait SpongeMode: private::SealedSpongeMode {} /// The absorbing state of the `Sponge`. #[derive(Debug)] From 5dd7de3cc7dd8f110534f36320809f9c41901b83 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 15 Dec 2021 15:24:01 +0000 Subject: [PATCH 57/59] Remove all uses of `PrimeField::Repr` in generic code `PrimeField::from_repr` explicitly leaves the endianness opaque. We therefore can't use it in places we were using `FieldExt::from_bytes` (which was specifically little-endian) generically, but the previous commit replaced it everywhere. We now handle generic contexts on a case-by-case basis: - Where we needed to convert bitstrings into field elements, we now use double-and-add on the field elements directly instead of on bytes. This is less efficient, but visible correct (and a future change to the `ff` crate APIs could enable the more efficient version). - `INV_TWO_POW_K`, which is pre-computed for `pallas::Base`, was being incorrectly used in a field-generic circuit. We now compute it live. - `test_zs_and_us` was only used in tests, and hard-coded a field element encoding length of 32 bytes. It now uses Pallas concretely. --- src/circuit/gadget/sinsemilla.rs | 30 ++++++++----------- src/circuit/gadget/utilities.rs | 25 +++++++--------- .../gadget/utilities/lookup_range_check.rs | 6 ++-- src/constants.rs | 10 +++---- 4 files changed, 29 insertions(+), 42 deletions(-) diff --git a/src/circuit/gadget/sinsemilla.rs b/src/circuit/gadget/sinsemilla.rs index 5412c3ab..4c653bb8 100644 --- a/src/circuit/gadget/sinsemilla.rs +++ b/src/circuit/gadget/sinsemilla.rs @@ -3,7 +3,7 @@ use crate::circuit::gadget::{ ecc::{self, EccInstructions}, utilities::Var, }; -use ff::PrimeField; +use group::ff::{Field, PrimeField}; use halo2::{circuit::Layouter, plonk::Error}; use pasta_curves::arithmetic::CurveAffine; use std::fmt::Debug; @@ -194,25 +194,19 @@ where // Closure to parse a bitstring (little-endian) into a base field element. let to_base_field = |bits: &[Option]| -> Option { - assert!(bits.len() <= C::Base::NUM_BITS as usize); + // To simplify the following logic, require that the all-ones bitstring is + // canonical in the field, by not allowing a length of NUM_BITS. + assert!(bits.len() < C::Base::NUM_BITS as usize); let bits: Option> = bits.iter().cloned().collect(); - let bytes: Option> = bits.map(|bits| { - // Pad bits to 256 bits - let pad_len = 256 - bits.len(); - let mut bits = bits; - bits.extend_from_slice(&vec![false; pad_len]); - - bits.chunks_exact(8) - .map(|byte| byte.iter().rev().fold(0u8, |acc, bit| acc * 2 + *bit as u8)) - .collect() - }); - bytes.map(|bytes| { - let mut repr = ::Repr::default(); - // The above code assumes the byte representation is 256 bits. - assert_eq!(repr.as_ref().len(), 32); - repr.as_mut().copy_from_slice(&bytes); - C::Base::from_repr(repr).unwrap() + bits.map(|bits| { + bits.into_iter().rev().fold(C::Base::zero(), |acc, bit| { + if bit { + acc.double() + C::Base::one() + } else { + acc.double() + } + }) }) }; diff --git a/src/circuit/gadget/utilities.rs b/src/circuit/gadget/utilities.rs index 58e291f7..e84a808b 100644 --- a/src/circuit/gadget/utilities.rs +++ b/src/circuit/gadget/utilities.rs @@ -87,27 +87,24 @@ pub fn ternary(a: Expression, b: Expression, c: Expression /// Takes a specified subsequence of the little-endian bit representation of a field element. /// The bits are numbered from 0 for the LSB. pub fn bitrange_subset(field_elem: &F, bitrange: Range) -> F { + // We can allow a subsequence of length NUM_BITS, because + // field_elem.to_le_bits() returns canonical bitstrings. assert!(bitrange.end <= F::NUM_BITS as usize); - let bits: Vec = field_elem + field_elem .to_le_bits() .iter() .by_val() .skip(bitrange.start) .take(bitrange.end - bitrange.start) - .chain(std::iter::repeat(false)) - .take(256) - .collect(); - let bytearray: Vec = bits - .chunks_exact(8) - .map(|byte| byte.iter().rev().fold(0u8, |acc, bit| acc * 2 + *bit as u8)) - .collect(); - - let mut repr = F::Repr::default(); - // The above code assumes the byte representation is 256 bits. - assert_eq!(repr.as_ref().len(), 32); - repr.as_mut().copy_from_slice(&bytearray); - F::from_repr(repr).unwrap() + .rev() + .fold(F::zero(), |acc, bit| { + if bit { + acc.double() + F::one() + } else { + acc.double() + } + }) } /// Check that an expression is in the small range [0..range), diff --git a/src/circuit/gadget/utilities/lookup_range_check.rs b/src/circuit/gadget/utilities/lookup_range_check.rs index 65f0eb81..04596ff5 100644 --- a/src/circuit/gadget/utilities/lookup_range_check.rs +++ b/src/circuit/gadget/utilities/lookup_range_check.rs @@ -364,7 +364,7 @@ impl LookupRangeCheckConfig mod tests { use super::LookupRangeCheckConfig; - use crate::primitives::sinsemilla::{INV_TWO_POW_K, K}; + use crate::primitives::sinsemilla::K; use crate::spec::lebs2ip; use ff::{Field, PrimeFieldBits}; use halo2::{ @@ -431,9 +431,7 @@ mod tests { .collect::>() }; let expected_zs = { - let mut repr = F::Repr::default(); - repr.as_mut().copy_from_slice(&INV_TWO_POW_K); - let inv_two_pow_k = F::from_repr(repr).unwrap(); + let inv_two_pow_k = F::from(1 << K).invert().unwrap(); chunks.iter().fold(vec![element], |mut zs, a_i| { // z_{i + 1} = (z_i - a_i) / 2^{K} let z = (zs[zs.len() - 1] - a_i) * inv_two_pow_k; diff --git a/src/constants.rs b/src/constants.rs index 0368e6ed..52df6cd5 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -248,17 +248,15 @@ fn test_lagrange_coeffs(base: C, num_windows: usize) { // 1. z + y = u^2, // 2. z - y is not a square // for the y-coordinate of each fixed-base multiple in each window. -fn test_zs_and_us(base: C, z: &[u64], u: &[[[u8; 32]; H]], num_windows: usize) { +fn test_zs_and_us(base: pallas::Affine, z: &[u64], u: &[[[u8; 32]; H]], num_windows: usize) { let window_table = compute_window_table(base, num_windows); for ((u, z), window_points) in u.iter().zip(z.iter()).zip(window_table) { for (u, point) in u.iter().zip(window_points.iter()) { let y = *point.coordinates().unwrap().y(); - let mut u_repr = ::Repr::default(); - u_repr.as_mut().copy_from_slice(u); - let u = C::Base::from_repr(u_repr).unwrap(); - assert_eq!(C::Base::from(*z) + y, u * u); // allow either square root - assert!(bool::from((C::Base::from(*z) - y).sqrt().is_none())); + let u = pallas::Base::from_repr(*u).unwrap(); + assert_eq!(pallas::Base::from(*z) + y, u * u); // allow either square root + assert!(bool::from((pallas::Base::from(*z) - y).sqrt().is_none())); } } } From 1be54d9f0dc9d33dee85a119ca5c013ce0c46e28 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 15 Dec 2021 15:42:05 +0000 Subject: [PATCH 58/59] Use `<= PrimeField::CAPACITY` instead of `< PrimeField::NUM_BITS` --- src/circuit/gadget/sinsemilla.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/circuit/gadget/sinsemilla.rs b/src/circuit/gadget/sinsemilla.rs index 4c653bb8..b3151ead 100644 --- a/src/circuit/gadget/sinsemilla.rs +++ b/src/circuit/gadget/sinsemilla.rs @@ -196,7 +196,7 @@ where let to_base_field = |bits: &[Option]| -> Option { // To simplify the following logic, require that the all-ones bitstring is // canonical in the field, by not allowing a length of NUM_BITS. - assert!(bits.len() < C::Base::NUM_BITS as usize); + assert!(bits.len() <= C::Base::CAPACITY as usize); let bits: Option> = bits.iter().cloned().collect(); bits.map(|bits| { From ab930e88667ab6a37913a50c7f0848764f06b97c Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 15 Dec 2021 16:29:28 +0000 Subject: [PATCH 59/59] sinsemilla: Simplify assertions in `MessagePiece::from_bitstring` Also fixes some incorrect code comments. Closes zcash/orchard#263. --- src/circuit/gadget/sinsemilla.rs | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/circuit/gadget/sinsemilla.rs b/src/circuit/gadget/sinsemilla.rs index b3151ead..6f58f95f 100644 --- a/src/circuit/gadget/sinsemilla.rs +++ b/src/circuit/gadget/sinsemilla.rs @@ -28,9 +28,9 @@ pub trait SinsemillaInstructions, _> = bitstring .chunks(piece_num_words * K) .enumerate() @@ -188,16 +188,13 @@ where assert_eq!(bitstring.len() % K, 0); let num_words = bitstring.len() / K; - // Message piece must be at most `ceil(C::Base::NUM_BITS / K)` bits - let piece_max_num_words = C::Base::NUM_BITS as usize / K; + // Each message piece must have at most `floor(C::Base::CAPACITY / K)` words. + // This ensures that the all-ones bitstring is canonical in the field. + let piece_max_num_words = C::Base::CAPACITY as usize / K; assert!(num_words <= piece_max_num_words as usize); // Closure to parse a bitstring (little-endian) into a base field element. let to_base_field = |bits: &[Option]| -> Option { - // To simplify the following logic, require that the all-ones bitstring is - // canonical in the field, by not allowing a length of NUM_BITS. - assert!(bits.len() <= C::Base::CAPACITY as usize); - let bits: Option> = bits.iter().cloned().collect(); bits.map(|bits| { bits.into_iter().rev().fold(C::Base::zero(), |acc, bit| {