diff --git a/Cargo.lock b/Cargo.lock index b3d07faf..5d3b028b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,12 +4,12 @@ version = 3 [[package]] name = "ahash" -version = "0.7.6" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" dependencies = [ + "cfg-if", "const-random", - "getrandom", "once_cell", "version_check", ] @@ -65,9 +65,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.71" +version = "1.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" +checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854" [[package]] name = "autocfg" @@ -116,9 +116,7 @@ dependencies = [ "clap", "digest", "plonky2", - "plonky2_ecdsa", - "plonky2_field", - "plonky2_u32", + "plonky2_gadgets", "rand", "serde_json", "sha2", @@ -133,9 +131,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "4.3.18" +version = "4.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b6396aa128fe4149d2af114f746eb048b5667e2844cc51ae90830f45de7ccb" +checksum = "5fd304a20bff958a57f04c4e96a2e7594cc4490a0e809cbd48bb6437edaa452d" dependencies = [ "clap_builder", "clap_derive", @@ -144,9 +142,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.3.18" +version = "4.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d011140df54d9c4c592974ccd7d694dd4ab5b92ea0436435fa900a211d6b0f6" +checksum = "01c6a3f08f1fe5662a35cfe393aec09c4df95f60ee93b7556505260f75eee9e1" dependencies = [ "anstream", "anstyle", @@ -163,7 +161,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.26", + "syn 2.0.27", ] [[package]] @@ -280,9 +278,9 @@ dependencies = [ [[package]] name = "either" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "errno" @@ -339,9 +337,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.12.3" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" dependencies = [ "ahash", "rayon", @@ -354,15 +352,6 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" -[[package]] -name = "hermit-abi" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" -dependencies = [ - "libc", -] - [[package]] name = "hermit-abi" version = "0.3.2" @@ -381,7 +370,7 @@ version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" dependencies = [ - "hermit-abi 0.3.2", + "hermit-abi", "rustix", "windows-sys", ] @@ -395,11 +384,20 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + [[package]] name = "itoa" -version = "1.0.6" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] name = "js-sys" @@ -449,9 +447,9 @@ dependencies = [ [[package]] name = "num" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43db66d1170d347f9a065114077f7dccb00c1b9478c89384490a3425279a4606" +checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" dependencies = [ "num-bigint", "num-complex", @@ -518,20 +516,20 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" dependencies = [ "autocfg", ] [[package]] name = "num_cpus" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi 0.2.6", + "hermit-abi", "libc", ] @@ -544,13 +542,13 @@ checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" [[package]] name = "plonky2" version = "0.1.3" -source = "git+https://github.com/mir-protocol/plonky2.git#3de92d9ed1721cec133e4e1e1b3ec7facb756ccf" +source = "git+https://github.com/mir-protocol/plonky2.git#bfa7ab369eebdd2284def26d830dfcfcdcd58c1b" dependencies = [ "ahash", "anyhow", "getrandom", "hashbrown", - "itertools", + "itertools 0.11.0", "keccak-hash", "log", "num", @@ -565,20 +563,6 @@ dependencies = [ "unroll", ] -[[package]] -name = "plonky2_ecdsa" -version = "0.1.0" -source = "git+ssh://git@github.com/succinctlabs/plonky2-ecdsa?branch=kevjue/serialization#028e81cce2f499487280287cbde8e04e6c2adb4c" -dependencies = [ - "anyhow", - "itertools", - "num", - "plonky2", - "plonky2_maybe_rayon", - "plonky2_u32", - "serde", -] - [[package]] name = "plonky2_field" version = "0.1.0" @@ -586,7 +570,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef0b0cfed734e8aec93ee0b49e3067a27111c355b9263fb1418bfe4c80656d12" dependencies = [ "anyhow", - "itertools", + "itertools 0.10.5", "num", "plonky2_util", "rand", @@ -596,23 +580,27 @@ dependencies = [ ] [[package]] -name = "plonky2_maybe_rayon" +name = "plonky2_gadgets" version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "655cdcdb13c260cdb42b29b55247f2f66479d14342b6be3dc688efc54d3e24c4" +source = "git+ssh://git@github.com/succinctlabs/plonky2-gadgets.git#c8c670282afbce2634b9dd82f673ab3755b68e61" dependencies = [ - "rayon", + "anyhow", + "digest", + "itertools 0.10.5", + "num", + "plonky2", + "serde_json", + "sha2", + "subtle-encoding", ] [[package]] -name = "plonky2_u32" +name = "plonky2_maybe_rayon" version = "0.1.0" -source = "git+ssh://git@github.com/succinctlabs/plonky2-u32?branch=kevjue/serialize#dde8b31d227501debbecbd5595116c986f3cf381" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "655cdcdb13c260cdb42b29b55247f2f66479d14342b6be3dc688efc54d3e24c4" dependencies = [ - "anyhow", - "itertools", - "num", - "plonky2", + "rayon", ] [[package]] @@ -645,18 +633,18 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.63" +version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b368fba921b0dce7e60f5e04ec15e565b3303972b42bcfde1d0713b881959eb" +checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.28" +version = "1.0.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488" +checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965" dependencies = [ "proc-macro2", ] @@ -728,34 +716,34 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.13" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" [[package]] name = "scopeguard" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "serde" -version = "1.0.171" +version = "1.0.175" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30e27d1e4fd7659406c492fd6cfaf2066ba8773de45ca75e855590f856dc34a9" +checksum = "5d25439cd7397d044e2748a6fe2432b5e85db703d6d097bd014b3c0ad1ebff0b" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.171" +version = "1.0.175" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "389894603bd18c46fa56231694f8d827779c0951a667087194cf9de94ed24682" +checksum = "b23f7ade6f110613c0d63858ddb8b94c1041f550eab58a16b371bdf2c9c80ab4" dependencies = [ "proc-macro2", "quote", - "syn 2.0.26", + "syn 2.0.27", ] [[package]] @@ -814,9 +802,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.26" +version = "2.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45c3457aacde3c65315de5031ec191ce46604304d2446e803d71ade03308d970" +checksum = "b60f673f44a8255b9c8c657daf66a596d435f2da81a555b06dc644d080ba45e0" dependencies = [ "proc-macro2", "quote", @@ -852,9 +840,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" +checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" [[package]] name = "unroll" @@ -905,7 +893,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.26", + "syn 2.0.27", "wasm-bindgen-shared", ] @@ -927,7 +915,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.26", + "syn 2.0.27", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -1006,6 +994,6 @@ checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" [[package]] name = "zeroize" -version = "1.3.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4756f7db3f7b5574938c3eb1c117038b8e07f95ee6718c0efad4ac21508f1efd" +checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" diff --git a/Cargo.toml b/Cargo.toml index 445e4d04..4a420628 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,9 +8,7 @@ anyhow = "1.0.71" clap = { version = "4.3.18", features = ["derive"] } digest = "0.10.7" plonky2 = { git = "https://github.com/mir-protocol/plonky2.git" } -plonky2_ecdsa = { git = "ssh://git@github.com/succinctlabs/plonky2-ecdsa", branch="kevjue/serialization" } -plonky2_field = "0.1.0" -plonky2_u32 = { git = "ssh://git@github.com/succinctlabs/plonky2-u32", branch="kevjue/serialize" } +plonky2_gadgets = { git = "ssh://git@github.com/succinctlabs/plonky2-gadgets.git" } rand = "0.8.5" serde_json = "1.0.103" sha2 = "0.10.7" diff --git a/src/bit_operations.rs b/src/bit_operations.rs deleted file mode 100644 index 23d46933..00000000 --- a/src/bit_operations.rs +++ /dev/null @@ -1,431 +0,0 @@ -use std::marker::PhantomData; - -use plonky2::gates::gate::Gate; -use plonky2::gates::util::StridedConstraintConsumer; -use plonky2::hash::hash_types::RichField; -use plonky2::iop::ext_target::ExtensionTarget; -use plonky2::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGeneratorRef}; -use plonky2::iop::target::BoolTarget; -use plonky2::iop::target::Target; -use plonky2::iop::witness::{PartitionWitness, Witness, WitnessWrite}; -use plonky2::plonk::circuit_builder::CircuitBuilder; -use plonky2::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; -use plonky2::util::serialization::{Buffer, IoResult, Read, Write}; -use plonky2_ecdsa::gadgets::biguint::CircuitBuilderBiguint; -use plonky2_field::extension::Extendable; -use plonky2_field::types::Field; - -use crate::helper::{biguint_to_bits_target, bits_to_biguint_target}; - -/* -a ^ b ^ c = a+b+c - 2*a*b - 2*a*c - 2*b*c + 4*a*b*c - = a*( 1 - 2*b - 2*c + 4*b*c ) + b + c - 2*b*c - = a*( 1 - 2*b -2*c + 4*m ) + b + c - 2*m -where m = b*c - */ -pub fn xor3, const D: usize>( - a: BoolTarget, - b: BoolTarget, - c: BoolTarget, - builder: &mut CircuitBuilder, -) -> BoolTarget { - // let gate_type = XOR3Gate::new_from_config(&builder.config); - // let gate = builder.add_gate(gate_type, vec![]); - // // let (row, copy) = builder.find_slot(gate, &[], &[]); - - // builder.connect(Target::wire(gate, 0), a.target); - // builder.connect(Target::wire(gate, 1), b.target); - // builder.connect(Target::wire(gate, 2), c.target); - // let output = BoolTarget::new_unsafe(Target::wire(gate, 3)); - // return output; - - let m = builder.mul(b.target, c.target); - let two_b = builder.add(b.target, b.target); - let two_c = builder.add(c.target, c.target); - let two_m = builder.add(m, m); - let four_m = builder.add(two_m, two_m); - let one = builder.one(); - let one_sub_two_b = builder.sub(one, two_b); - let one_sub_two_b_sub_two_c = builder.sub(one_sub_two_b, two_c); - let one_sub_two_b_sub_two_c_add_four_m = builder.add(one_sub_two_b_sub_two_c, four_m); - let mut res = builder.mul(a.target, one_sub_two_b_sub_two_c_add_four_m); - res = builder.add(res, b.target); - res = builder.add(res, c.target); - - BoolTarget::new_unsafe(builder.sub(res, two_m)) -} - -pub fn xor3_arr, const D: usize, const S: usize>( - a: [BoolTarget; S], - b: [BoolTarget; S], - c: [BoolTarget; S], - builder: &mut CircuitBuilder, -) -> [BoolTarget; S] { - let mut res = [None; S]; - for i in 0..S { - res[i] = Some(xor3(a[i], b[i], c[i], builder)); - } - - let gate_type = XOR3Gate::new(16); - let gate = builder.add_gate(gate_type, vec![]); - - for i in 0..16 { - builder.connect( - Target::wire(gate, XOR3Gate::wire_ith_a(i)), - a[16 + i].target, - ); - builder.connect( - Target::wire(gate, XOR3Gate::wire_ith_b(i)), - b[16 + i].target, - ); - builder.connect( - Target::wire(gate, XOR3Gate::wire_ith_c(i)), - c[16 + i].target, - ); - res[16 + i] = Some(BoolTarget::new_unsafe(Target::wire( - gate, - XOR3Gate::wire_ith_d(i), - ))); - } - - res.map(|x| x.unwrap()) -} - -pub fn xor3_arr_slow, const D: usize, const S: usize>( - a: [BoolTarget; S], - b: [BoolTarget; S], - c: [BoolTarget; S], - builder: &mut CircuitBuilder, -) -> [BoolTarget; S] { - let mut res = [None; S]; - for i in 0..S { - res[i] = Some(xor3(a[i], b[i], c[i], builder)); - } - res.map(|x| x.unwrap()) -} - -pub fn xor2_arr, const D: usize, const S: usize>( - a: [BoolTarget; S], - b: [BoolTarget; S], - builder: &mut CircuitBuilder, -) -> [BoolTarget; S] { - let mut res = [None; S]; - let zero = builder.zero(); - for i in 0..S { - let a_b = builder.mul(a[i].target, b[i].target); - let two_a_b = builder.mul_const(F::ONE + F::ONE, a_b); - let a_plus_b = builder.add(a[i].target, b[i].target); - res[i] = Some(BoolTarget::new_unsafe(builder.sub(a_plus_b, two_a_b))); - } - - let gate_type = XOR3Gate::new(16); - let gate = builder.add_gate(gate_type, vec![]); - - for i in 0..16 { - builder.connect( - Target::wire(gate, XOR3Gate::wire_ith_a(i)), - a[16 + i].target, - ); - builder.connect( - Target::wire(gate, XOR3Gate::wire_ith_b(i)), - b[16 + i].target, - ); - builder.connect(Target::wire(gate, XOR3Gate::wire_ith_c(i)), zero); - res[16 + i] = Some(BoolTarget::new_unsafe(Target::wire( - gate, - XOR3Gate::wire_ith_d(i), - ))); - } - - res.map(|x| x.unwrap()) -} - -pub fn xor2_arr_slow, const D: usize, const S: usize>( - a: [BoolTarget; S], - b: [BoolTarget; S], - builder: &mut CircuitBuilder, -) -> [BoolTarget; S] { - let mut res = [None; S]; - for i in 0..S { - let a_b = builder.mul(a[i].target, b[i].target); - let two_a_b = builder.mul_const(F::ONE + F::ONE, a_b); - let a_plus_b = builder.add(a[i].target, b[i].target); - res[i] = Some(BoolTarget::new_unsafe(builder.sub(a_plus_b, two_a_b))); - } - - res.map(|x| x.unwrap()) -} - -pub fn and_arr, const D: usize, const S: usize>( - a: [BoolTarget; S], - b: [BoolTarget; S], - builder: &mut CircuitBuilder, -) -> [BoolTarget; S] { - let mut res = [None; S]; - for i in 0..S { - res[i] = Some(builder.and(a[i], b[i])); - } - res.map(|x| x.unwrap()) -} - -pub fn not_arr, const D: usize, const S: usize>( - a: [BoolTarget; S], - builder: &mut CircuitBuilder, -) -> [BoolTarget; S] { - let mut res = [None; S]; - for i in 0..S { - res[i] = Some(builder.not(a[i])); - } - res.map(|x| x.unwrap()) -} - -pub fn zip_add, const D: usize, const S: usize>( - a: [[BoolTarget; S]; 8], - b: [[BoolTarget; S]; 8], - builder: &mut CircuitBuilder, -) -> [[BoolTarget; S]; 8] { - let mut res = [None; 8]; - for i in 0..8 { - res[i] = Some(add_arr(a[i], b[i], builder)); - } - res.map(|x| x.unwrap()) -} - -pub fn add_arr, const D: usize, const S: usize>( - a: [BoolTarget; S], - b: [BoolTarget; S], - builder: &mut CircuitBuilder, -) -> [BoolTarget; S] { - // First convert a, b into biguint with limbs of 32 bits each - let a_biguint = bits_to_biguint_target(builder, a.to_vec()); - let b_biguint = bits_to_biguint_target(builder, b.to_vec()); - // Then add a and b are big uints - let sum_biguint = builder.add_biguint(&a_biguint, &b_biguint); - let mut sum_bits = biguint_to_bits_target::(builder, &sum_biguint); - - // sum_bits is in big-endian format. - // we need to return the S least significant bits in big-endian format - let mut res = [None; S]; - sum_bits.reverse(); - for i in 0..S { - res[i] = Some(sum_bits[S - 1 - i]); - } - res.map(|x| x.unwrap()) -} - -/// A gate which can perform a weighted multiply-add, i.e. `result = c0 x y + c1 z`. If the config -/// supports enough routed wires, it can support several such operations in one gate. -#[derive(Debug, Clone)] -pub struct XOR3Gate { - pub num_xors: usize, -} - -impl XOR3Gate { - pub fn new(num_xors: usize) -> Self { - Self { num_xors } - } - - pub fn wire_ith_a(i: usize) -> usize { - i * 4 - } - - pub fn wire_ith_b(i: usize) -> usize { - i * 4 + 1 - } - - pub fn wire_ith_c(i: usize) -> usize { - i * 4 + 2 - } - - pub fn wire_ith_d(i: usize) -> usize { - i * 4 + 3 - } -} - -impl, const D: usize> Gate for XOR3Gate { - fn id(&self) -> String { - format!("{self:?}") - } - - fn serialize(&self, dst: &mut Vec) -> IoResult<()> { - dst.write_usize(self.num_xors) - } - - fn deserialize(src: &mut Buffer) -> IoResult { - let num_xors = src.read_usize()?; - Ok(Self { num_xors }) - } - - fn eval_unfiltered(&self, vars: EvaluationVars) -> Vec { - let mut constraints = Vec::new(); - - let one = F::Extension::from_canonical_u64(1); - let two = F::Extension::from_canonical_u64(2); - let four = F::Extension::from_canonical_u64(4); - let mut acc = F::Extension::from_canonical_u64(0); - - for i in 0..self.num_xors { - let a = vars.local_wires[XOR3Gate::wire_ith_a(i)]; - let b = vars.local_wires[XOR3Gate::wire_ith_b(i)]; - let c = vars.local_wires[XOR3Gate::wire_ith_c(i)]; - let d = vars.local_wires[XOR3Gate::wire_ith_d(i)]; - let output = a * (one - two * b - two * c + four * b * c) + b + c - two * b * c - d; - acc += output; - } - - constraints.push(acc); - - constraints - } - - fn eval_unfiltered_base_one( - &self, - vars: EvaluationVarsBase, - mut yield_constr: StridedConstraintConsumer, - ) { - let one = F::from_canonical_u64(1); - let two = F::from_canonical_u64(2); - let four = F::from_canonical_u64(4); - - let mut acc = F::from_canonical_u64(0); - for i in 0..self.num_xors { - let a = vars.local_wires[XOR3Gate::wire_ith_a(i)]; - let b = vars.local_wires[XOR3Gate::wire_ith_b(i)]; - let c = vars.local_wires[XOR3Gate::wire_ith_c(i)]; - let d = vars.local_wires[XOR3Gate::wire_ith_d(i)]; - let output = a * (one - two * b - two * c + four * b * c) + b + c - two * b * c - d; - acc += output; - } - - yield_constr.one(acc); - } - - fn eval_unfiltered_circuit( - &self, - builder: &mut CircuitBuilder, - vars: EvaluationTargets, - ) -> Vec> { - let one = builder.one_extension(); - let two = builder.two_extension(); - let four = builder.constant_extension(F::Extension::from_canonical_u64(4)); - let mut acc = builder.zero_extension(); - - for i in 0..self.num_xors { - let a = vars.local_wires[XOR3Gate::wire_ith_a(i)]; - let b = vars.local_wires[XOR3Gate::wire_ith_b(i)]; - let c = vars.local_wires[XOR3Gate::wire_ith_c(i)]; - let d = vars.local_wires[XOR3Gate::wire_ith_d(i)]; - - let two_b = builder.mul_extension(two, b); - let two_c = builder.mul_extension(two, c); - let bc = builder.mul_extension(b, c); - let four_bc = builder.mul_extension(four, bc); - let two_bc = builder.mul_extension(two, bc); - - // a * (one - two * b - two * c + four * b * c) + b + c - two * b * c - d; - - let mut output = builder.sub_extension(one, two_b); - output = builder.sub_extension(output, two_c); - output = builder.add_extension(output, four_bc); - output = builder.mul_extension(a, output); - output = builder.add_extension(output, b); - output = builder.add_extension(output, c); - output = builder.sub_extension(output, two_bc); - output = builder.sub_extension(output, d); - - acc = builder.add_extension(acc, output); - } - - vec![acc] - } - - fn generators(&self, row: usize, _local_constants: &[F]) -> Vec> { - let gen = XOR3Generator:: { - row, - num_xors: self.num_xors, - _phantom: PhantomData, - }; - vec![WitnessGeneratorRef::new(gen.adapter())] - } - - fn num_wires(&self) -> usize { - 4 - } - - fn num_constants(&self) -> usize { - 0 - } - - fn degree(&self) -> usize { - 3 - } - - fn num_constraints(&self) -> usize { - 1 - } -} - -#[derive(Debug, Default)] -pub struct XOR3Generator, const D: usize> { - row: usize, - num_xors: usize, - _phantom: PhantomData, -} - -impl, const D: usize> SimpleGenerator for XOR3Generator { - fn id(&self) -> String { - "XOR3Generator".to_string() - } - - fn serialize(&self, dst: &mut Vec) -> IoResult<()> { - dst.write_usize(self.row)?; - dst.write_usize(self.num_xors) - } - - fn deserialize(src: &mut Buffer) -> IoResult { - let row = src.read_usize()?; - let num_xors = src.read_usize()?; - Ok(Self { - row, - num_xors, - _phantom: PhantomData, - }) - } - - fn dependencies(&self) -> Vec { - let local_target = |column| Target::wire(self.row, column); - let mut result: Vec = Vec::new(); - - for i in 0..self.num_xors { - result.push(local_target(i * 4)); - result.push(local_target(i * 4 + 1)); - result.push(local_target(i * 4 + 2)); - } - - result - } - - /* - a ^ b ^ c = a+b+c - 2*a*b - 2*a*c - 2*b*c + 4*a*b*c - = a*( 1 - 2*b - 2*c + 4*b*c ) + b + c - 2*b*c - = a*( 1 - 2*b -2*c + 4*m ) + b + c - 2*m - where m = b*c - */ - fn run_once(&self, witness: &PartitionWitness, out_buffer: &mut GeneratedValues) { - let get_wire = |wire: usize| -> F { witness.get_target(Target::wire(self.row, wire)) }; - - let one = F::from_canonical_u64(1); - let two = F::from_canonical_u64(2); - let four = F::from_canonical_u64(4); - - for i in 0..self.num_xors { - let a = get_wire(4 * i); - let b = get_wire(4 * i + 1); - let c = get_wire(4 * i + 2); - let d_target = Target::wire(self.row, 4 * i + 3); - let computed_output = - a * (one - two * b - two * c + four * b * c) + b + c - two * b * c; - out_buffer.set_target(d_target, computed_output); - } - } -} diff --git a/src/helper.rs b/src/helper.rs deleted file mode 100644 index 688f0506..00000000 --- a/src/helper.rs +++ /dev/null @@ -1,102 +0,0 @@ -use plonky2::hash::hash_types::RichField; -use plonky2::iop::target::BoolTarget; -use plonky2::plonk::circuit_builder::CircuitBuilder; -use plonky2_ecdsa::gadgets::biguint::BigUintTarget; -use plonky2_field::extension::Extendable; -use plonky2_u32::gadgets::arithmetic_u32::U32Target; - -pub fn _right_rotate(n: [BoolTarget; S], bits: usize) -> [BoolTarget; S] { - let mut res = [None; S]; - for i in 0..S { - res[i] = Some(n[((S - bits) + i) % S]) - } - res.map(|x| x.unwrap()) -} - -pub fn _shr, const D: usize, const S: usize>( - n: [BoolTarget; S], - bits: i64, - builder: &mut CircuitBuilder, -) -> [BoolTarget; S] { - let mut res = [None; S]; - for i in 0..S { - if (i as i64) < bits { - res[i] = Some(BoolTarget::new_unsafe(builder.constant(F::ZERO))); - } else { - res[i] = Some(n[(i as i64 - bits) as usize]); - } - } - res.map(|x| x.unwrap()) -} - -pub fn uint64_to_bits, const D: usize>( - value: u64, - builder: &mut CircuitBuilder, -) -> [BoolTarget; 64] { - let mut bits = [None; 64]; - for i in 0..64 { - if value & (1 << (63 - i)) != 0 { - bits[i] = Some(BoolTarget::new_unsafe(builder.constant(F::ONE))); - } else { - bits[i] = Some(BoolTarget::new_unsafe(builder.constant(F::ZERO))); - } - } - bits.map(|x| x.unwrap()) -} - -pub fn uint32_to_bits, const D: usize>( - value: u32, - builder: &mut CircuitBuilder, -) -> [BoolTarget; 32] { - let mut bits = [None; 32]; - for i in 0..32 { - if value & (1 << (31 - i)) != 0 { - bits[i] = Some(BoolTarget::new_unsafe(builder.constant(F::ONE))); - } else { - bits[i] = Some(BoolTarget::new_unsafe(builder.constant(F::ZERO))); - } - } - bits.map(|x| x.unwrap()) -} - -pub fn biguint_to_bits_target, const D: usize, const B: usize>( - builder: &mut CircuitBuilder, - a: &BigUintTarget, -) -> Vec { - let mut res = Vec::new(); - for i in (0..a.num_limbs()).rev() { - let bit_targets = builder.split_le_base::(a.get_limb(i).0, 32); - for j in (0..32).rev() { - res.push(BoolTarget::new_unsafe(bit_targets[j])); - } - } - res -} - -// The bits_target needs to be in big-endian format. -pub fn bits_to_biguint_target, const D: usize>( - builder: &mut CircuitBuilder, - bits_target: Vec, -) -> BigUintTarget { - let bit_len = bits_target.len(); - assert_eq!(bit_len % 32, 0); - - let mut u32_targets = Vec::new(); - for i in 0..bit_len / 32 { - u32_targets.push(U32Target( - builder.le_sum(bits_target[i * 32..(i + 1) * 32].iter().rev()), - )); - } - u32_targets.reverse(); - BigUintTarget { limbs: u32_targets } -} - -pub fn byte_to_u32_target, const D: usize>( - builder: &mut CircuitBuilder, - bits_target: Vec, -) -> U32Target { - let bit_len = bits_target.len(); - assert_eq!(bit_len, 8); - - U32Target(builder.le_sum(bits_target.iter().rev())) -} diff --git a/src/main.rs b/src/main.rs index d704d0f1..01366bd1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,10 +1,5 @@ -pub mod bit_operations; -pub mod helper; pub mod merkle; pub mod scripts; -pub mod sha256; -pub mod u32; -pub mod u8; pub mod utils; pub mod validator; diff --git a/src/scripts/generate_tests.rs b/src/scripts/generate_tests.rs index 7ae773ec..c21b6100 100644 --- a/src/scripts/generate_tests.rs +++ b/src/scripts/generate_tests.rs @@ -5,10 +5,10 @@ use subtle_encoding::hex; pub fn generate_tendermint_test_cases(num_validators: usize) { let mut rng = rand::thread_rng(); - // Generate an array of byte arrays where the byte arrays have variable length between 38 and 47 bytes and the total length of the array is less than n + // Generate an array of byte arrays where the byte arrays have variable length between 38 and 46 bytes and the total length of the array is less than n let random_bytes: Vec> = (0..num_validators) .map(|_| { - let inner_length = rng.gen_range(38..=47); + let inner_length = rng.gen_range(38..=46); (0..inner_length).map(|_| rng.gen()).collect() }) .collect(); diff --git a/src/sha256.rs b/src/sha256.rs deleted file mode 100644 index 00cf3740..00000000 --- a/src/sha256.rs +++ /dev/null @@ -1,431 +0,0 @@ -use plonky2::hash::hash_types::RichField; -use plonky2::iop::target::BoolTarget; -use plonky2::plonk::circuit_builder::CircuitBuilder; -use plonky2_field::extension::Extendable; -use plonky2_u32::gadgets::arithmetic_u32::CircuitBuilderU32; - -use crate::bit_operations::{add_arr, and_arr, not_arr, xor2_arr, xor3_arr, zip_add}; -use crate::helper::{_right_rotate, _shr, uint32_to_bits}; - -pub struct Sha256Target { - pub message: Vec, - pub digest: Vec, -} - -fn get_initial_hash, const D: usize>( - builder: &mut CircuitBuilder, -) -> [[BoolTarget; 32]; 8] { - let initial_hash = [ - 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, - 0x5be0cd19, - ]; - let mut res = [None; 8]; - for i in 0..8 { - res[i] = Some(uint32_to_bits(initial_hash[i], builder)); - } - res.map(|x| x.unwrap()) -} - -fn get_round_constants, const D: usize>( - builder: &mut CircuitBuilder, -) -> [[BoolTarget; 32]; 64] { - let round_constants: [u32; 64] = [ - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, - 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, - 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, - 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, - 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, - 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, - 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, - 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, - 0xc67178f2, - ]; - let mut res = [None; 64]; - for i in 0..64 { - res[i] = Some(uint32_to_bits(round_constants[i], builder)); - } - res.map(|x| x.unwrap()) -} - -fn reshape(u: Vec) -> Vec<[BoolTarget; 32]> { - let l = u.len() / 32; - let mut res = Vec::new(); - for i in 0..l { - let mut arr = [None; 32]; - for j in 0..32 { - arr[j] = Some(u[i * 32 + j]); - } - res.push(arr.map(|x| x.unwrap())); - } - res -} - -// Generate the 32-byte SHA-256 hash of the message. -// reference: https://github.com/thomdixon/pysha2/blob/master/sha2/sha256.py -pub fn sha256, const D: usize>( - builder: &mut CircuitBuilder, - message: Vec, -) -> Vec { - let mut msg_input = Vec::new(); - // Add signals for the input msg - for _ in 0..message.len() { - msg_input.push(builder.add_virtual_bool_target_safe()); // Will verify that input is 0 or 1 - } - - // Constrain the input msg to be the same as the message - for i in 0..message.len() { - builder.connect(msg_input[i].target, message[i].target); - } - - let mdi = (message.len() / 8) % 64; - let length = (message.len() / 8) << 3; // length in bytes - let padlen = if mdi < 56 { 55 - mdi } else { 119 - mdi }; - - msg_input.push(builder.constant_bool(true)); - for _ in 0..7 { - msg_input.push(builder.constant_bool(false)); - } - - for _ in 0..padlen * 8 { - msg_input.push(builder.constant_bool(false)); - } - - for i in (0..64).rev() { - // big endian binary representation of length - msg_input.push(builder.constant_bool((length >> i) & 1 == 1)); - } - - let mut sha256_hash = get_initial_hash(builder); - let round_constants = get_round_constants(builder); - - // Process the input with 512 bit chunks aka 64 byte chunks - for chunk_start in (0..msg_input.len()).step_by(512) { - let chunk = msg_input[chunk_start..chunk_start + 512].to_vec(); - let mut u = Vec::new(); - - for i in 0..512 { - // 0 .. 16 chunk size * 32 bits7 - u.push(chunk[i]); - } - for _ in 512..64 * 32 { - // 16 * 8 ... 64 * 8 because of L - u.push(builder.constant_bool(false)); - } - - let mut w = reshape(u); - for i in 16..64 { - let s0 = xor3_arr( - _right_rotate(w[i - 15], 7), - _right_rotate(w[i - 15], 18), - _shr(w[i - 15], 3, builder), - builder, - ); - let s1 = xor3_arr( - _right_rotate(w[i - 2], 17), - _right_rotate(w[i - 2], 19), - _shr(w[i - 2], 10, builder), - builder, - ); - let inter1 = add_arr(w[i - 16], s0, builder); - let inter2 = add_arr(inter1, w[i - 7], builder); - w[i] = add_arr(inter2, s1, builder); - } - let mut a = sha256_hash[0]; - let mut b = sha256_hash[1]; - let mut c = sha256_hash[2]; - let mut d = sha256_hash[3]; - let mut e = sha256_hash[4]; - let mut f = sha256_hash[5]; - let mut g = sha256_hash[6]; - let mut h = sha256_hash[7]; - - for i in 0..64 { - let sum1 = xor3_arr( - _right_rotate(e, 6), - _right_rotate(e, 11), - _right_rotate(e, 25), - builder, - ); - let ch = xor2_arr( - and_arr(e, f, builder), - and_arr(not_arr(e, builder), g, builder), - builder, - ); - let temp1 = add_arr(h, sum1, builder); - let temp2 = add_arr(temp1, ch, builder); - let temp3 = add_arr(temp2, round_constants[i], builder); - let temp4 = add_arr(temp3, w[i], builder); - let final_temp1 = temp4; - - let sum0 = xor3_arr( - _right_rotate(a, 2), - _right_rotate(a, 13), - _right_rotate(a, 22), - builder, - ); - - let maj = xor3_arr( - and_arr(a, b, builder), - and_arr(a, c, builder), - and_arr(b, c, builder), - builder, - ); - let final_temp2 = add_arr(sum0, maj, builder); - - h = g; - g = f; - f = e; - e = add_arr(d, final_temp1, builder); - d = c; - c = b; - b = a; - a = add_arr(final_temp1, final_temp2, builder); - } - - sha256_hash = zip_add(sha256_hash, [a, b, c, d, e, f, g, h], builder); - } - - let mut digest = Vec::new(); - for word in sha256_hash.iter() { - for i in 0..word.len() { - digest.push(word[i]); - } - } - - // Constrain the output of the hash to the correct length. - let digest_len_const = builder.constant(F::from_canonical_usize(digest.len())); - let hash_len_const = builder.constant(F::from_canonical_usize(32 * 8 as usize)); - builder.connect(digest_len_const, hash_len_const); - - return digest; -} - -#[cfg(test)] -mod tests { - use anyhow::Result; - use plonky2::iop::witness::{PartialWitness, WitnessWrite}; - use plonky2::plonk::circuit_builder::CircuitBuilder; - use plonky2::plonk::circuit_data::CircuitConfig; - use plonky2::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; - use subtle_encoding::hex::decode; - - use crate::sha256::sha256; - - fn to_bits(msg: Vec) -> Vec { - let mut res = Vec::new(); - for i in 0..msg.len() { - let char = msg[i]; - for j in 0..8 { - if (char & (1 << 7 - j)) != 0 { - res.push(true); - } else { - res.push(false); - } - } - } - res - } - - #[test] - fn test_sha256_bench() -> Result<()> { - let mut msg = String::new(); - for _ in 0..8 { - msg.push_str("abcdefghij"); - } - let msg_bits = to_bits(msg.as_bytes().to_vec()); - let expected_digest = "d68d62c262c2ec08961c1104188cde86f51695878759666ad61490c8ec66745c"; - let digest_bits = to_bits(decode(expected_digest).unwrap()); - - const D: usize = 2; - type C = PoseidonGoldilocksConfig; - type F = >::F; - let mut builder = CircuitBuilder::::new(CircuitConfig::standard_recursion_config()); - - let mut targets = Vec::new(); - for i in 0..msg_bits.len() { - targets.push(builder.constant_bool(msg_bits[i])); - } - let msg_hash = sha256(&mut builder, targets.clone()); - - for i in 0..digest_bits.len() { - if digest_bits[i] { - builder.assert_one(msg_hash[i].target); - } else { - builder.assert_zero(msg_hash[i].target); - } - } - - let data = builder.build::(); - - for i in 0..10 { - let mut pw = PartialWitness::new(); - - for i in 0..msg_bits.len() { - pw.set_bool_target(targets[i], msg_bits[i]); - } - let now = std::time::Instant::now(); - let _proof = data.prove(pw).unwrap(); - println!("{} step, time elapsed {}", i, now.elapsed().as_millis()); - } - - Ok(()) - } - - #[test] - fn test_sha256_empty() -> Result<()> { - let msg = b""; - let msg_bits = to_bits(msg.to_vec()); - let expected_digest = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"; - let digest_bits = to_bits(decode(expected_digest).unwrap()); - - const D: usize = 2; - type C = PoseidonGoldilocksConfig; - type F = >::F; - let mut builder = CircuitBuilder::::new(CircuitConfig::standard_recursion_config()); - - let mut targets = Vec::new(); - for i in 0..msg_bits.len() { - targets.push(builder.constant_bool(msg_bits[i])); - } - let msg_hash = sha256(&mut builder, targets.clone()); - - for i in 0..digest_bits.len() { - if digest_bits[i] { - builder.assert_one(msg_hash[i].target); - } else { - builder.assert_zero(msg_hash[i].target); - } - } - - let mut pw = PartialWitness::new(); - - for i in 0..msg_bits.len() { - pw.set_bool_target(targets[i], msg_bits[i]); - } - - let data = builder.build::(); - let proof = data.prove(pw).unwrap(); - - data.verify(proof) - } - - #[test] - fn test_sha256_small_msg() -> Result<()> { - let msg = b"plonky2"; - let msg_bits = to_bits(msg.to_vec()); - let expected_digest = "8943a85083f16e93dc92d6af455841daacdae5081aa3125b614a626df15461eb"; - let digest_bits = to_bits(decode(expected_digest).unwrap()); - - const D: usize = 2; - type C = PoseidonGoldilocksConfig; - type F = >::F; - let mut builder = CircuitBuilder::::new(CircuitConfig::standard_recursion_config()); - let mut targets = Vec::new(); - for i in 0..msg_bits.len() { - targets.push(builder.constant_bool(msg_bits[i])); - } - let msg_hash = sha256(&mut builder, targets.clone()); - - for i in 0..digest_bits.len() { - if digest_bits[i] { - builder.assert_one(msg_hash[i].target); - } else { - builder.assert_zero(msg_hash[i].target); - } - } - - let mut pw = PartialWitness::new(); - - for i in 0..msg_bits.len() { - pw.set_bool_target(targets[i], msg_bits[i]); - } - - let data = builder.build::(); - let proof = data.prove(pw).unwrap(); - - data.verify(proof) - } - - #[test] - fn test_sha256_large_msg() -> Result<()> { - let msg = decode( - "00de6ad0941095ada2a7996e6a888581928203b8b69e07ee254d289f5b9c9caea193c2ab01902d", - ) - .unwrap(); - let msg_bits = to_bits(msg.to_vec()); - // dbg!(&msg_bits); - let expected_digest = "84f633a570a987326947aafd434ae37f151e98d5e6d429137a4cc378d4a7988e"; - dbg!(decode(expected_digest).unwrap()); - let digest_bits = to_bits(decode(expected_digest).unwrap()); - - const D: usize = 2; - type C = PoseidonGoldilocksConfig; - type F = >::F; - let mut builder = CircuitBuilder::::new(CircuitConfig::standard_ecc_config()); - - let mut targets = Vec::new(); - for i in 0..msg_bits.len() { - targets.push(builder.constant_bool(msg_bits[i])); - } - let msg_hash = sha256(&mut builder, targets.clone()); - - for i in 0..digest_bits.len() { - if digest_bits[i] { - builder.assert_one(msg_hash[i].target); - } else { - builder.assert_zero(msg_hash[i].target); - } - } - - let mut pw = PartialWitness::new(); - - for i in 0..msg_bits.len() { - pw.set_bool_target(targets[i], msg_bits[i]); - } - - dbg!(builder.num_gates()); - let data = builder.build::(); - let proof = data.prove(pw).unwrap(); - - data.verify(proof) - } - - #[test] - #[should_panic] - fn test_sha512_failure() { - let msg = decode("35c323757c20640a294345c89c0bfcebe3d554fdb0c7b7a0bdb72222c531b1ecf7ec1c43f4de9d49556de87b86b26a98942cb078486fdb44de38b80864c3973153756363696e6374204c616273").unwrap(); - let msg_bits = to_bits(msg.to_vec()); - let expected_digest = "9fcee6fbeadc123c38d5a97dbe58f8257b4906820d627425af668b94b795e74e"; - let digest_bits = to_bits(decode(expected_digest).unwrap()); - - const D: usize = 2; - type C = PoseidonGoldilocksConfig; - type F = >::F; - let mut builder = CircuitBuilder::::new(CircuitConfig::standard_recursion_config()); - - let mut targets = Vec::new(); - for i in 0..msg_bits.len() { - targets.push(builder.constant_bool(msg_bits[i])); - } - let msg_hash = sha256(&mut builder, targets.clone()); - - for i in 0..digest_bits.len() { - if digest_bits[i] { - builder.assert_one(msg_hash[i].target); - } else { - builder.assert_zero(msg_hash[i].target); - } - } - let mut pw = PartialWitness::new(); - - for i in 0..msg_bits.len() { - pw.set_bool_target(targets[i], msg_bits[i]); - } - - let data = builder.build::(); - let proof = data.prove(pw).unwrap(); - - data.verify(proof).expect("sha256 error"); - } -} diff --git a/src/u32.rs b/src/u32.rs deleted file mode 100644 index 98d46d9f..00000000 --- a/src/u32.rs +++ /dev/null @@ -1,26 +0,0 @@ -use plonky2::{ - hash::hash_types::RichField, - iop::target::{BoolTarget, Target}, - plonk::circuit_builder::CircuitBuilder, -}; -use plonky2_field::extension::Extendable; - -#[derive(Debug, Clone, Copy)] -pub struct U32Target(pub Target); - -pub trait U32Builder { - fn u32_to_bits_le(&mut self, num: U32Target) -> [BoolTarget; 32]; -} - -impl, const D: usize> U32Builder for CircuitBuilder { - fn u32_to_bits_le(&mut self, byte: U32Target) -> [BoolTarget; 32] { - // Note: The gate being used under the hood here is probably unoptimized for this usecase. - // In particular, we can "batch decompose" the bits to fill the entire width of the table. - let mut res = [self._false(); 32]; - let bits = self.split_le(byte.0, 32); - for i in 0..32 { - res[i] = bits[i]; - } - return res; - } -} diff --git a/src/u8.rs b/src/u8.rs deleted file mode 100644 index e0aef98b..00000000 --- a/src/u8.rs +++ /dev/null @@ -1,41 +0,0 @@ -use plonky2::{ - hash::hash_types::RichField, - iop::target::{BoolTarget, Target}, - plonk::circuit_builder::CircuitBuilder, -}; -use plonky2_field::extension::Extendable; - -#[derive(Debug, Clone, Copy)] -pub struct U8Target(pub Target); - -pub trait U8Builder { - /// Creates a zero byte. - fn zero_u8(&mut self) -> U8Target; - - /// Creates a new byte from an existing target. - fn new_u8(&mut self, target: Target) -> U8Target; - - /// Splits a single byte into bits in little-endian order. - fn u8_to_bits_le(&mut self, byte: U8Target) -> [BoolTarget; 8]; -} - -impl, const D: usize> U8Builder for CircuitBuilder { - fn zero_u8(&mut self) -> U8Target { - U8Target(self.zero()) - } - - fn new_u8(&mut self, target: Target) -> U8Target { - U8Target(target) - } - - fn u8_to_bits_le(&mut self, byte: U8Target) -> [BoolTarget; 8] { - // Note: The gate being used under the hood here is probably unoptimized for this usecase. - // In particular, we can "batch decompose" the bits to fill the entire width of the table. - let mut res = [self._false(); 8]; - let bits = self.split_le(byte.0, 8); - for i in 0..8 { - res[i] = bits[i]; - } - return res; - } -} diff --git a/src/validator.rs b/src/validator.rs index 90971e18..2a9c5118 100644 --- a/src/validator.rs +++ b/src/validator.rs @@ -8,14 +8,14 @@ //! read more about them here: https://protobuf.dev/programming-guides/encoding/#varints. use plonky2::iop::target::{BoolTarget, Target}; use plonky2::{hash::hash_types::RichField, plonk::circuit_builder::CircuitBuilder}; -use plonky2_field::extension::Extendable; +use plonky2::field::extension::Extendable; +use plonky2_gadgets::hash::sha::sha256::sha256; +use plonky2_gadgets::num::u32::gadgets::arithmetic_u32::{U32Target, CircuitBuilderU32}; use crate::merkle::{HASH_SIZE, HASH_SIZE_BITS}; -use crate::sha256::sha256; -use crate::u32::{U32Builder, U32Target}; /// The maximum length of a protobuf-encoded Tendermint validator in bytes. -const VALIDATOR_BYTE_LENGTH_MAX: usize = 47; +const VALIDATOR_BYTE_LENGTH_MAX: usize = 46; /// The maximum length of a protobuf-encoded Tendermint validator in bits. const VALIDATOR_BIT_LENGTH_MAX: usize = VALIDATOR_BYTE_LENGTH_MAX * 8; @@ -273,7 +273,7 @@ impl, const D: usize> TendermintMarshaller for Circ } // Load the output of the hash. - let hash = sha256(self, validator_bits); + let hash = sha256(self, &validator_bits); for k in 0..HASH_SIZE_BITS { validator_bytes_hashes[j][k] = hash[k]; } @@ -380,7 +380,7 @@ impl, const D: usize> TendermintMarshaller for Circ // Load the output of the hash. // Note: Calculate the inner hash as if both validators are enabled. - let inner_hash = sha256(self, message_bits); + let inner_hash = sha256(self, &message_bits); for k in 0..HASH_SIZE_BITS { // If the left node is enabled and the right node is disabled, we pass up the left hash. @@ -457,7 +457,7 @@ pub(crate) mod tests { config::{GenericConfig, PoseidonGoldilocksConfig}, }, }; - use plonky2_field::types::Field; + use plonky2::field::types::Field; use sha2::Sha256; use subtle_encoding::hex; @@ -465,8 +465,9 @@ pub(crate) mod tests { use crate::merkle::{hash_all_leaves, HASH_SIZE_BITS}; + use plonky2_gadgets::num::u32::gadgets::arithmetic_u32::U32Target; + use crate::{ - u32::U32Target, utils::{bits_to_bytes, f_bits_to_bytes}, validator::{I64Target, TendermintMarshaller}, }; @@ -576,11 +577,7 @@ pub(crate) mod tests { let config = CircuitConfig::standard_recursion_config(); let mut builder = CircuitBuilder::::new(config); - let validators: Vec<&str> = vec![ - "de6ad0941095ada2a7996e6a888581928203b8b69e07ee254d289f5b9c9caea193c2ab01902d", - "92fbe0c52937d80c5ea643c7832620b84bfdf154ec7129b8b471a63a763f2fe955af1ac65fd3", - "e902f88b2371ff6243bf4b0ebe8f46205e00749dd4dad07b2ea34350a1f9ceedb7620ab913c2", - ]; + let validators: Vec<&str> = vec!["6694200ba0e084f7184255abedc39af04463a4ff11e0e0c1326b1b82ea1de50c6b35cf6efa8f7ed3", "739d312e54353379a852b43de497ca4ec52bb49f59b7294a4d6cf19dd648e16cb530b7a7a1e35875d4ab4d90", "4277f2f871f3e041bcd4643c0cf18e5a931c2bfe121ce8983329a289a2b0d2161745a2ddf99bade9a1"]; let validators_bytes: Vec> = validators .iter() @@ -630,13 +627,13 @@ pub(crate) mod tests { let config = CircuitConfig::standard_recursion_config(); let mut builder = CircuitBuilder::::new(config); - // Generated array with byte arrays with variable length [38, 47] bytes (to mimic validator bytes), and computed the validator hash corresponding to a merkle tree of depth 2 formed by these validator bytes. - let validators: Vec<&str> = vec!["97b8cc20f17618415186ec0efca0f8a24a070b5e844f3abdaa03436c4cb58af32c3bde71e391", "5f407f30abdec9e3c4f5e8c95d0df93d5977acb7e686dd1dfc331a57f7c693756334f8252ca6b17f5a971fa891a9c7", "0daac88e983737ca1ed37da4fff6c87651deb410b3811dd6d6c0a9ff023a4655ef61d1240d60fe5f"]; + // Generated array with byte arrays with variable length [38, 46] bytes (to mimic validator bytes), and computed the validator hash corresponding to a merkle tree of depth 2 formed by these validator bytes. + let validators: Vec<&str> = vec!["6694200ba0e084f7184255abedc39af04463a4ff11e0e0c1326b1b82ea1de50c6b35cf6efa8f7ed3", "739d312e54353379a852b43de497ca4ec52bb49f59b7294a4d6cf19dd648e16cb530b7a7a1e35875d4ab4d90", "4277f2f871f3e041bcd4643c0cf18e5a931c2bfe121ce8983329a289a2b0d2161745a2ddf99bade9a1"]; let (validators_target, validator_byte_length, validator_enabled) = generate_inputs(&mut builder, &validators); - let expected_digest = "9e75a6467742596100e170527f6c74e654acf208278276025d7448d3ddb211b6"; + let expected_digest = "d3430135bc6ed16a421ef1b8ec45d4d8b3e335e479f2bc3b074e9f1ed1d8f67e"; let digest_bits = to_bits(hex::decode(expected_digest).unwrap()); println!( @@ -675,13 +672,13 @@ pub(crate) mod tests { let config = CircuitConfig::standard_recursion_config(); let mut builder = CircuitBuilder::::new(config); - // Generated array with byte arrays with variable length [38, 47] bytes (to mimic validator bytes), and computed the validator hash corresponding to a merkle tree of depth 2 formed by these validator bytes. - let validators: Vec<&str> = vec!["864711afc2c955c5bfcc65300d678ba7a5793fc74c629abaae3becaa5ac9e8d7dbd586a1e02fe7b30dd63c9f84b6ba", "b9ec50c618a22ca150f1157af35e0c530b3f7a1a96174f74aa85d86eabbe570efd36b0c73e49fc2725652f94989c"]; + // Generated array with byte arrays with variable length [38, 46] bytes (to mimic validator bytes), and computed the validator hash corresponding to a merkle tree of depth 2 formed by these validator bytes. + let validators: Vec<&str> = vec!["364db94241a02b701d0dc85ac016fab2366fba326178e6f11d8294931969072b7441fd6b0ff5129d6867", "6fa0cef8f328eb8e2aef2084599662b1ee0595d842058966166029e96bd263e5367185f19af67b099645ec08aa"]; let (validators_target, validator_byte_length, validator_enabled) = generate_inputs(&mut builder, &validators); - let expected_digest = "a47148d62d235d74db7619c00bfa0e8c6ad0564fe0ac7b81b78edfa18dd329b3"; + let expected_digest = "be110ff9abb6bdeaebf48ac8e179a76fda1f6eaef0150ca6159587f489722204"; let digest_bits = to_bits(hex::decode(expected_digest).unwrap()); println!(