From 78464265094d7f30459e8a140bcb188c17d085d9 Mon Sep 17 00:00:00 2001 From: Your Name Date: Thu, 24 Apr 2025 07:11:04 -0400 Subject: [PATCH] fast --- src/circuit.rs | 140 +++++++++++++++++++++++++------------------------ src/main.rs | 11 ++-- 2 files changed, 80 insertions(+), 71 deletions(-) diff --git a/src/circuit.rs b/src/circuit.rs index 569dff6..63b429b 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -1,6 +1,5 @@ use crate::{gate::Gate, gate_type::GateType}; - #[derive(Debug, Clone)] pub struct Circuit { pub input_bits: Vec, // Input wires @@ -9,7 +8,7 @@ pub struct Circuit { impl Circuit { pub fn eval(self) -> bool { - let mut evaluated_gates = vec!(); + let mut evaluated_gates = vec![]; for gate in self.gates { let result = gate.eval(&self.input_bits, &evaluated_gates); @@ -18,8 +17,8 @@ impl Circuit { match evaluated_gates.pop() { Some(result) => result, - None => panic!("Bruh moment") - } + None => panic!("Bruh moment"), + } } /* @@ -27,13 +26,17 @@ impl Circuit { bits) is greater than the second number B (encoded in the next n bits) . */ pub fn compare_n_bit_numbers(input_bits: Vec, n: usize) -> Self { - if input_bits.len() < 2*n { - panic!("Expected input_bits to be of at least length {}, but it was {}", 2*n, input_bits.len()) + if input_bits.len() < 2 * n { + panic!( + "Expected input_bits to be of at least length {}, but it was {}", + 2 * n, + input_bits.len() + ) } /* - base case n=1: 1-bit: - + base case n=1: 1-bit: + A B | A > B ----------- 0 0 | 0 @@ -62,81 +65,82 @@ impl Circuit { 1 1 1 0 | 1 | 1 1 1 1 1 | 0 | 0 - The inductive pattern should become apparent now. - For illustration here's the case for n=4, which should show the - recursive characteristics of the formula. + The inductive pattern should become apparent now. + For illustration here's the case for n=4, which should show the + recursive characteristics of the formula. - (A3 > B3) || - ((A3 == B3) && (A2 > B2)) || + (A3 > B3) || + ((A3 == B3) && (A2 > B2)) || ((A3 == B3) && (A2 == B2) && (A1 > B1)) || ((A3 == B3) && (A2 == B2) && (A1 == B1)) && (A0 > B0)) */ let gates = create_n_bit_comparator_gates(n); - return Circuit { input_bits, gates } + return Circuit { input_bits, gates }; } } - -fn create_n_bit_comparator_gates(n: usize) -> Vec{ +fn create_n_bit_comparator_gates(n: usize) -> Vec { let mut indices: Vec = vec![0; n]; - let mut all_gates: Vec = vec!(); - let mut and_gate_indices: Vec = vec!(); - - + let mut all_gates: Vec = Vec::with_capacity(1+3*n); + let mut and_gate_indices: Vec = vec![0; n]; - rec_n_bit_comperator_gates(0, n, &mut all_gates, &mut and_gate_indices, &mut indices, ); + for curr in 0..n { + // Gate(A_current > B_current) + let gt_gate = Gate::new(GateType::Bigger, vec![], vec![curr, curr + n]); + let gt_gate_index = all_gates.len(); + all_gates.push(gt_gate); + + // print!("( ({}) ", format!("{} > {}", format!("A{}", n-1-curr), format!("B{}", n-1-curr))); + + let mut current_bit_gate_indices: Vec = Vec::with_capacity(curr+1); + current_bit_gate_indices.push(gt_gate_index); + + // Bit to the left of curr. The one at array-index 0 doesn't have one. + if curr != 0 { + // Gate(A_i = B_i) + let eq_gate = Gate::new(GateType::Equal, vec![], vec![curr - 1, curr - 1 + n]); + // remember which gate-index this bit belongs to. + indices[n - curr] = all_gates.len(); + all_gates.push(eq_gate); + } + + for i in 0..curr { + // Translate i to the key'th bit position because the array index does not match the bit index + // i.e. + // + // let input_bits = vec![ + // A2 A1 A0 <- A_key + // 0 1 2 <- i iterates all array indices less than curr + // false, false, true, + // + // B2 B1 B0 + // 3 4 5 + // false, true, false + // ]; + let key = n - 1 - i; + + // print!("&& ({}) ", format!("{} = {}", format!("A{}", key), format!("B{}", key))); + + // Index of Gate(A_i = B_i). + // You could maybe find a solution without the indices vector but it's insanely cheap anyway and maybe even better + let eq_gate_index = indices[key]; + current_bit_gate_indices.push(eq_gate_index); + } + + // The AND spanning all gates for this bit + let and_gate_index = all_gates.len(); + let and_gate = Gate::new(GateType::And, current_bit_gate_indices, vec![]); + + // println!(")"); + all_gates.push(and_gate); + and_gate_indices.push(and_gate_index); + } // the OR spanning all ANDs - let or_gate = Gate::new( GateType::Or, and_gate_indices, vec!()); - + let or_gate = Gate::new(GateType::Or, and_gate_indices, vec![]); all_gates.push(or_gate); return all_gates; } - -fn rec_n_bit_comperator_gates(curr: usize, max: usize, all_gates: &mut Vec, and_gate_incides: &mut Vec, indices: &mut Vec){ - // Incrementing gate index - let a_curr_gt_b_curr_gate_index = all_gates.len(); - - // Gate(A_current > B_current) - let a_curr_gt_b_curr_gate = Gate::new(GateType::Bigger, vec!(), vec!(curr, curr+max)); - - // A_current>B_current - //print!(" ( ({}) ", format!("{} > {}", format!("A{}", max-1-curr), format!("B{}", max-1-curr))); - - all_gates.push(a_curr_gt_b_curr_gate); - - let mut this_recursion_gate_indices: Vec = vec!(a_curr_gt_b_curr_gate_index); - - for i in 0..curr { - let key = max-1-i; - if i == curr-1 { - // Gate(A_current > B_current) - let a_i_eq_b_i_gate = Gate::new(GateType::Equal, vec!(), vec!(i, i+max)); - let a_curr_gt_b_curr_gate_index = all_gates.len(); - indices[key] = a_curr_gt_b_curr_gate_index; - all_gates.push(a_i_eq_b_i_gate); - } - let eq_gate_index = indices[key]; - - //print!("&& ({}) ", format!("{} = {}", format!("A{}", key), format!("B{}", key))); - - // Index of this equality gate - this_recursion_gate_indices.push(eq_gate_index); - } - - let and_curr_index = all_gates.len(); - let and_curr_gate = Gate::new(GateType::And, this_recursion_gate_indices, vec!()); - - all_gates.push(and_curr_gate); - and_gate_incides.push(and_curr_index); - - if curr+1 == max { - //println!(")"); - return; - } - //println!(") ||"); - return rec_n_bit_comperator_gates(curr+1, max, all_gates, and_gate_incides, indices); -} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index b5b3437..41d9aae 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,11 @@ -use apet_ex1::circuit::Circuit; +use apet_ex1::{circuit::Circuit, scalar_to_bits::scalar_to_bits}; +use curve25519_dalek::Scalar; +use num_bigint::BigUint; +use rand::rngs::OsRng; fn main() { +/* + let input_bits = vec![ // A2 A1 A0 // 0 1 2 @@ -14,7 +19,8 @@ fn main() { let c = Circuit::compare_n_bit_numbers(input_bits, 3); let res = c.eval(); println!("1 > 2 ? {}", res); -/* +*/ + let a = Scalar::random(&mut OsRng); let b = Scalar::random(&mut OsRng); // Convert to bit representation @@ -34,5 +40,4 @@ fn main() { let b_int = BigUint::from_bytes_le(&b.to_bytes()); println!("{}", circuit_result == (a_int > b_int)) -*/ }