works
This commit is contained in:
@@ -0,0 +1 @@
|
|||||||
|
/target
|
||||||
Generated
+288
@@ -0,0 +1,288 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 4
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "apet_ex1"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"curve25519-dalek",
|
||||||
|
"num-bigint",
|
||||||
|
"num-traits",
|
||||||
|
"rand",
|
||||||
|
"rand_core 0.4.2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "autocfg"
|
||||||
|
version = "1.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg-if"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cpufeatures"
|
||||||
|
version = "0.2.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crypto-common"
|
||||||
|
version = "0.1.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
|
||||||
|
dependencies = [
|
||||||
|
"generic-array",
|
||||||
|
"typenum",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "curve25519-dalek"
|
||||||
|
version = "4.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"cpufeatures",
|
||||||
|
"curve25519-dalek-derive",
|
||||||
|
"digest",
|
||||||
|
"fiat-crypto",
|
||||||
|
"rand_core 0.6.4",
|
||||||
|
"rustc_version",
|
||||||
|
"subtle",
|
||||||
|
"zeroize",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "curve25519-dalek-derive"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "digest"
|
||||||
|
version = "0.10.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
|
||||||
|
dependencies = [
|
||||||
|
"crypto-common",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fiat-crypto"
|
||||||
|
version = "0.2.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "generic-array"
|
||||||
|
version = "0.14.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
|
||||||
|
dependencies = [
|
||||||
|
"typenum",
|
||||||
|
"version_check",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "getrandom"
|
||||||
|
version = "0.2.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"wasi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.172"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-bigint"
|
||||||
|
version = "0.4.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9"
|
||||||
|
dependencies = [
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-integer"
|
||||||
|
version = "0.1.46"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-traits"
|
||||||
|
version = "0.2.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ppv-lite86"
|
||||||
|
version = "0.2.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
|
||||||
|
dependencies = [
|
||||||
|
"zerocopy",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.95"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.40"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand"
|
||||||
|
version = "0.8.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"rand_chacha",
|
||||||
|
"rand_core 0.6.4",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_chacha"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||||
|
dependencies = [
|
||||||
|
"ppv-lite86",
|
||||||
|
"rand_core 0.6.4",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_core"
|
||||||
|
version = "0.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_core"
|
||||||
|
version = "0.6.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustc_version"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
|
||||||
|
dependencies = [
|
||||||
|
"semver",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "semver"
|
||||||
|
version = "1.0.26"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "subtle"
|
||||||
|
version = "2.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "2.0.100"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "typenum"
|
||||||
|
version = "1.18.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ident"
|
||||||
|
version = "1.0.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "version_check"
|
||||||
|
version = "0.9.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasi"
|
||||||
|
version = "0.11.0+wasi-snapshot-preview1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerocopy"
|
||||||
|
version = "0.8.24"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879"
|
||||||
|
dependencies = [
|
||||||
|
"zerocopy-derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerocopy-derive"
|
||||||
|
version = "0.8.24"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zeroize"
|
||||||
|
version = "1.8.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
|
||||||
+14
@@ -0,0 +1,14 @@
|
|||||||
|
[package]
|
||||||
|
name = "apet_ex1"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
stdout=[]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
curve25519-dalek = { version = "4.1.3", features = ["rand_core", "digest"] }
|
||||||
|
rand = "0.8.5"
|
||||||
|
rand_core = "0.4"
|
||||||
|
num-bigint = "0.4"
|
||||||
|
num-traits = "0.2"
|
||||||
+149
@@ -0,0 +1,149 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use crate::{gate::Gate, gate_type::GateType};
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Circuit {
|
||||||
|
pub input_bits: Vec<bool>, // Input wires
|
||||||
|
pub gates: Vec<Gate>, // All gates
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Circuit {
|
||||||
|
pub fn eval(self) -> bool {
|
||||||
|
let mut evaluated_gates = vec!();
|
||||||
|
|
||||||
|
for gate in self.gates {
|
||||||
|
let result = gate.eval(&self.input_bits, &evaluated_gates);
|
||||||
|
evaluated_gates.push(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
match evaluated_gates.pop() {
|
||||||
|
Some(result) => result,
|
||||||
|
None => panic!("Bruh moment")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
This method should create a circuit that outputs 1 if the first number A (encoded in the first n
|
||||||
|
bits) is greater than the second number B (encoded in the next n bits) .
|
||||||
|
*/
|
||||||
|
pub fn compare_n_bit_numbers(input_bits: Vec<bool>, 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())
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
base case n=1: 1-bit:
|
||||||
|
|
||||||
|
A B | A > B
|
||||||
|
-----------
|
||||||
|
0 0 | 0
|
||||||
|
0 1 | 0
|
||||||
|
1 0 | 1
|
||||||
|
1 1 | 0
|
||||||
|
|
||||||
|
n+1 case: 2-bit:
|
||||||
|
|
||||||
|
A1 A0 B1 B0 | A > B | (A1 > B1) || ((A1 == B1) && (A0 > B0))
|
||||||
|
----------------------|------------------------------------
|
||||||
|
0 0 0 0 | 0 | 0
|
||||||
|
0 0 0 1 | 0 | 0
|
||||||
|
0 0 1 0 | 0 | 0
|
||||||
|
0 0 1 1 | 0 | 0
|
||||||
|
0 1 0 0 | 1 | 1
|
||||||
|
0 1 0 1 | 0 | 0
|
||||||
|
0 1 1 0 | 0 | 0
|
||||||
|
0 1 1 1 | 1 | 1
|
||||||
|
1 0 0 0 | 1 | 1
|
||||||
|
1 0 0 1 | 1 | 1
|
||||||
|
1 0 1 0 | 0 | 0
|
||||||
|
1 0 1 1 | 0 | 0
|
||||||
|
1 1 0 0 | 1 | 1
|
||||||
|
1 1 0 1 | 1 | 1
|
||||||
|
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.
|
||||||
|
|
||||||
|
(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 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn create_n_bit_comparator_gates(n: usize) -> Vec<Gate>{
|
||||||
|
let mut indices = HashMap::<String, usize>::new();
|
||||||
|
let mut all_gates: Vec<Gate> = vec!();
|
||||||
|
let mut and_gate_indices: Vec<usize> = vec!();
|
||||||
|
|
||||||
|
rec_n_bit_comperator_gates(0, n, &mut all_gates, &mut and_gate_indices, &mut indices, );
|
||||||
|
|
||||||
|
// the OR spanning all ANDs
|
||||||
|
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<Gate>, and_gate_incides: &mut Vec<usize>, indices: &mut HashMap<String, usize>){
|
||||||
|
// 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<usize> = vec!(a_curr_gt_b_curr_gate_index);
|
||||||
|
|
||||||
|
for i in 0..curr {
|
||||||
|
// A_i
|
||||||
|
let a_i = format!("A{}", max-1-i);
|
||||||
|
//B_i
|
||||||
|
let b_i = format!("B{}", max-1-i);
|
||||||
|
|
||||||
|
// A_i=B_i
|
||||||
|
let a_i_eq_b_i = format!("{} = {}", a_i, b_i);
|
||||||
|
// The curr-1'th equality gate is the only one that doesn't exist yet
|
||||||
|
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.insert(a_i_eq_b_i.clone(), a_curr_gt_b_curr_gate_index);
|
||||||
|
all_gates.push(a_i_eq_b_i_gate);
|
||||||
|
}
|
||||||
|
let eq_gate_index = indices.get(&a_i_eq_b_i).unwrap();
|
||||||
|
|
||||||
|
//print!("&& ({}) ", a_i_eq_b_i);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
+122
@@ -0,0 +1,122 @@
|
|||||||
|
use crate::gate_type::GateType;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Gate {
|
||||||
|
pub gate_type: GateType,
|
||||||
|
pub input_gates_indices: Vec<usize>, // Which previous gates to use
|
||||||
|
pub input_bits_indices: Vec<usize>, // Which input bits to use
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Gate {
|
||||||
|
pub fn new(
|
||||||
|
gate_type: GateType,
|
||||||
|
input_gates_indices: Vec<usize>,
|
||||||
|
input_bits_indices: Vec<usize>,
|
||||||
|
) -> Self {
|
||||||
|
let num_input_wires = input_bits_indices.len() + input_gates_indices.len();
|
||||||
|
|
||||||
|
if num_input_wires == 0 {
|
||||||
|
panic!("A gate without inputs is invalid");
|
||||||
|
}
|
||||||
|
|
||||||
|
if gate_type == GateType::Bigger && num_input_wires != 2 {
|
||||||
|
if num_input_wires != 2 {
|
||||||
|
panic!("Bigger gates need exactly two inputs")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if gate_type == GateType::Equal && num_input_wires != 2 {
|
||||||
|
if num_input_wires != 2 {
|
||||||
|
panic!("Equal gates need exactly two inputs")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Self {
|
||||||
|
gate_type,
|
||||||
|
input_gates_indices,
|
||||||
|
input_bits_indices,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn eval(&self, input_bits: &Vec<bool>, evaluated_gates: &Vec<bool>) -> bool {
|
||||||
|
/*
|
||||||
|
The goal is to perform short-circuit evaluation with the minimum number of vector lookups.
|
||||||
|
*/
|
||||||
|
|
||||||
|
match self.gate_type {
|
||||||
|
/*
|
||||||
|
A multi-input gate that outputs 1 if all input bits are 1, and 0 otherwise
|
||||||
|
*/
|
||||||
|
GateType::And => {
|
||||||
|
|
||||||
|
for &index in self.input_bits_indices.iter(){
|
||||||
|
if !input_bits[index] {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for &index in self.input_gates_indices.iter(){
|
||||||
|
if !evaluated_gates[index] {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
A multi-input gate that outputs 1 if at least one input bit is 1, and 0 otherwise.
|
||||||
|
*/
|
||||||
|
GateType::Or => {
|
||||||
|
for &index in self.input_bits_indices.iter(){
|
||||||
|
if input_bits[index] {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for &index in self.input_gates_indices.iter(){
|
||||||
|
if evaluated_gates[index] {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
A gate with exactly two inputs. It outputs 1 if the two input bits are equal
|
||||||
|
(i.e., both 0 or both 1), and 0 otherwise
|
||||||
|
*/
|
||||||
|
GateType::Equal => match self.input_bits_indices.len() {
|
||||||
|
0 => evaluated_gates[self.input_gates_indices[0]] == evaluated_gates[self.input_gates_indices[1]],
|
||||||
|
1 => input_bits[self.input_bits_indices[0]] == evaluated_gates[self.input_gates_indices[0]],
|
||||||
|
2 => {
|
||||||
|
input_bits[self.input_bits_indices[0]] == input_bits[self.input_bits_indices[1]]
|
||||||
|
},
|
||||||
|
_ => panic!{"How'd we get here?"}
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
A gate with exactly two inputs. It outputs 1 if the first input is 1 and the second
|
||||||
|
input is 0; otherwise, it outputs 0. This gate is used to compare individual bits a_i > b_i
|
||||||
|
|
||||||
|
A B | A > B | A && !B
|
||||||
|
--------------------
|
||||||
|
0 0 | 0 | 0 0 1
|
||||||
|
0 1 | 0 | 0 0 0
|
||||||
|
1 0 | 1 | 1 1 1
|
||||||
|
1 1 | 0 | 1 0 0
|
||||||
|
*/
|
||||||
|
GateType::Bigger => match self.input_bits_indices.len() {
|
||||||
|
// bits: [] gates: [A,B]
|
||||||
|
0 => evaluated_gates[self.input_gates_indices[0]] && !evaluated_gates[self.input_gates_indices[1]],
|
||||||
|
|
||||||
|
// bits: [A] gates: [B]
|
||||||
|
1 => input_bits[self.input_bits_indices[0]] && !evaluated_gates[self.input_gates_indices[0]],
|
||||||
|
|
||||||
|
// bits: [A,B] gates: []
|
||||||
|
2 => {
|
||||||
|
input_bits[self.input_bits_indices[0]] && !input_bits[self.input_bits_indices[1]]
|
||||||
|
},
|
||||||
|
|
||||||
|
_ => panic!{"How'd we get here? {}", input_bits.len()}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub enum GateType {
|
||||||
|
And, // multi-input
|
||||||
|
Or, // multi-input
|
||||||
|
Equal, // 2-input
|
||||||
|
Bigger, // 2-input (A > B)
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
pub mod circuit;
|
||||||
|
pub mod gate;
|
||||||
|
pub mod gate_type;
|
||||||
|
pub mod scalar_to_bits;
|
||||||
+26
@@ -0,0 +1,26 @@
|
|||||||
|
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 a = Scalar::random(&mut OsRng);
|
||||||
|
let b = Scalar::random(&mut OsRng);
|
||||||
|
// Convert to bit representation
|
||||||
|
let a_bits = scalar_to_bits(&a);
|
||||||
|
let b_bits = scalar_to_bits(&b);
|
||||||
|
|
||||||
|
// Combine A and B bits into one input vector
|
||||||
|
let mut input_bits = Vec::with_capacity(512);
|
||||||
|
input_bits.extend_from_slice(&a_bits);
|
||||||
|
input_bits.extend_from_slice(&b_bits);
|
||||||
|
|
||||||
|
// Build and evaluate the comparison circuit
|
||||||
|
let circuit = Circuit::compare_n_bit_numbers(input_bits, 256);
|
||||||
|
let circuit_result = circuit.eval();
|
||||||
|
|
||||||
|
let a_int = BigUint::from_bytes_le(&a.to_bytes());
|
||||||
|
let b_int = BigUint::from_bytes_le(&b.to_bytes());
|
||||||
|
|
||||||
|
println!("{}", circuit_result == (a_int > b_int))
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
use curve25519_dalek::Scalar;
|
||||||
|
|
||||||
|
pub fn scalar_to_bits(scalar: &Scalar) -> Vec<bool> {
|
||||||
|
let bytes = scalar.to_bytes();
|
||||||
|
let mut bits = Vec::with_capacity(256);
|
||||||
|
|
||||||
|
// MSB first
|
||||||
|
for &byte in bytes.iter().rev() {
|
||||||
|
for i in (0..8).rev() {
|
||||||
|
let bit = (byte >> i) & 1;
|
||||||
|
bits.push(bit != 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bits
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use apet_ex1::{circuit::Circuit, scalar_to_bits::scalar_to_bits};
|
||||||
|
use curve25519_dalek::scalar::Scalar;
|
||||||
|
use num_bigint::BigUint;
|
||||||
|
use rand::rngs::OsRng;
|
||||||
|
#[test]
|
||||||
|
fn test_scalar_comparison_via_circuit() {
|
||||||
|
for _ in 0..100 {
|
||||||
|
let a = Scalar::random(&mut OsRng);
|
||||||
|
let b = Scalar::random(&mut OsRng);
|
||||||
|
|
||||||
|
// Convert to bit representation
|
||||||
|
let a_bits = scalar_to_bits(&a);
|
||||||
|
let b_bits = scalar_to_bits(&b);
|
||||||
|
|
||||||
|
// Combine A and B bits into one input vector
|
||||||
|
let mut input_bits = Vec::with_capacity(512);
|
||||||
|
input_bits.extend_from_slice(&a_bits);
|
||||||
|
input_bits.extend_from_slice(&b_bits);
|
||||||
|
|
||||||
|
// Build and evaluate the comparison circuit
|
||||||
|
let circuit = Circuit::compare_n_bit_numbers(input_bits, 256);
|
||||||
|
let circuit_result = circuit.eval();
|
||||||
|
|
||||||
|
// Compare expected result using BigUint
|
||||||
|
let a_int = BigUint::from_bytes_le(&a.to_bytes());
|
||||||
|
let b_int = BigUint::from_bytes_le(&b.to_bytes());
|
||||||
|
let expected = a_int > b_int;
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
circuit_result, expected,
|
||||||
|
"Mismatch: A = {:?}, B = {:?}, A > B = {}, but circuit says {}",
|
||||||
|
a_int, b_int, expected, circuit_result
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user