Browse Source

works

master
Your Name 2 weeks ago
commit
dfed917799
10 changed files with 665 additions and 0 deletions
  1. 1
    0
      .gitignore
  2. 288
    0
      Cargo.lock
  3. 14
    0
      Cargo.toml
  4. 149
    0
      src/circuit.rs
  5. 122
    0
      src/gate.rs
  6. 7
    0
      src/gate_type.rs
  7. 4
    0
      src/lib.rs
  8. 26
    0
      src/main.rs
  9. 16
    0
      src/scalar_to_bits.rs
  10. 38
    0
      tests/test.rs

+ 1
- 0
.gitignore View File

@@ -0,0 +1 @@
1
+/target

+ 288
- 0
Cargo.lock View File

@@ -0,0 +1,288 @@
1
+# This file is automatically @generated by Cargo.
2
+# It is not intended for manual editing.
3
+version = 4
4
+
5
+[[package]]
6
+name = "apet_ex1"
7
+version = "0.1.0"
8
+dependencies = [
9
+ "curve25519-dalek",
10
+ "num-bigint",
11
+ "num-traits",
12
+ "rand",
13
+ "rand_core 0.4.2",
14
+]
15
+
16
+[[package]]
17
+name = "autocfg"
18
+version = "1.4.0"
19
+source = "registry+https://github.com/rust-lang/crates.io-index"
20
+checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
21
+
22
+[[package]]
23
+name = "cfg-if"
24
+version = "1.0.0"
25
+source = "registry+https://github.com/rust-lang/crates.io-index"
26
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
27
+
28
+[[package]]
29
+name = "cpufeatures"
30
+version = "0.2.17"
31
+source = "registry+https://github.com/rust-lang/crates.io-index"
32
+checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
33
+dependencies = [
34
+ "libc",
35
+]
36
+
37
+[[package]]
38
+name = "crypto-common"
39
+version = "0.1.6"
40
+source = "registry+https://github.com/rust-lang/crates.io-index"
41
+checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
42
+dependencies = [
43
+ "generic-array",
44
+ "typenum",
45
+]
46
+
47
+[[package]]
48
+name = "curve25519-dalek"
49
+version = "4.1.3"
50
+source = "registry+https://github.com/rust-lang/crates.io-index"
51
+checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be"
52
+dependencies = [
53
+ "cfg-if",
54
+ "cpufeatures",
55
+ "curve25519-dalek-derive",
56
+ "digest",
57
+ "fiat-crypto",
58
+ "rand_core 0.6.4",
59
+ "rustc_version",
60
+ "subtle",
61
+ "zeroize",
62
+]
63
+
64
+[[package]]
65
+name = "curve25519-dalek-derive"
66
+version = "0.1.1"
67
+source = "registry+https://github.com/rust-lang/crates.io-index"
68
+checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
69
+dependencies = [
70
+ "proc-macro2",
71
+ "quote",
72
+ "syn",
73
+]
74
+
75
+[[package]]
76
+name = "digest"
77
+version = "0.10.7"
78
+source = "registry+https://github.com/rust-lang/crates.io-index"
79
+checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
80
+dependencies = [
81
+ "crypto-common",
82
+]
83
+
84
+[[package]]
85
+name = "fiat-crypto"
86
+version = "0.2.9"
87
+source = "registry+https://github.com/rust-lang/crates.io-index"
88
+checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d"
89
+
90
+[[package]]
91
+name = "generic-array"
92
+version = "0.14.7"
93
+source = "registry+https://github.com/rust-lang/crates.io-index"
94
+checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
95
+dependencies = [
96
+ "typenum",
97
+ "version_check",
98
+]
99
+
100
+[[package]]
101
+name = "getrandom"
102
+version = "0.2.15"
103
+source = "registry+https://github.com/rust-lang/crates.io-index"
104
+checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
105
+dependencies = [
106
+ "cfg-if",
107
+ "libc",
108
+ "wasi",
109
+]
110
+
111
+[[package]]
112
+name = "libc"
113
+version = "0.2.172"
114
+source = "registry+https://github.com/rust-lang/crates.io-index"
115
+checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
116
+
117
+[[package]]
118
+name = "num-bigint"
119
+version = "0.4.6"
120
+source = "registry+https://github.com/rust-lang/crates.io-index"
121
+checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9"
122
+dependencies = [
123
+ "num-integer",
124
+ "num-traits",
125
+]
126
+
127
+[[package]]
128
+name = "num-integer"
129
+version = "0.1.46"
130
+source = "registry+https://github.com/rust-lang/crates.io-index"
131
+checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
132
+dependencies = [
133
+ "num-traits",
134
+]
135
+
136
+[[package]]
137
+name = "num-traits"
138
+version = "0.2.19"
139
+source = "registry+https://github.com/rust-lang/crates.io-index"
140
+checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
141
+dependencies = [
142
+ "autocfg",
143
+]
144
+
145
+[[package]]
146
+name = "ppv-lite86"
147
+version = "0.2.21"
148
+source = "registry+https://github.com/rust-lang/crates.io-index"
149
+checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
150
+dependencies = [
151
+ "zerocopy",
152
+]
153
+
154
+[[package]]
155
+name = "proc-macro2"
156
+version = "1.0.95"
157
+source = "registry+https://github.com/rust-lang/crates.io-index"
158
+checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
159
+dependencies = [
160
+ "unicode-ident",
161
+]
162
+
163
+[[package]]
164
+name = "quote"
165
+version = "1.0.40"
166
+source = "registry+https://github.com/rust-lang/crates.io-index"
167
+checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
168
+dependencies = [
169
+ "proc-macro2",
170
+]
171
+
172
+[[package]]
173
+name = "rand"
174
+version = "0.8.5"
175
+source = "registry+https://github.com/rust-lang/crates.io-index"
176
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
177
+dependencies = [
178
+ "libc",
179
+ "rand_chacha",
180
+ "rand_core 0.6.4",
181
+]
182
+
183
+[[package]]
184
+name = "rand_chacha"
185
+version = "0.3.1"
186
+source = "registry+https://github.com/rust-lang/crates.io-index"
187
+checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
188
+dependencies = [
189
+ "ppv-lite86",
190
+ "rand_core 0.6.4",
191
+]
192
+
193
+[[package]]
194
+name = "rand_core"
195
+version = "0.4.2"
196
+source = "registry+https://github.com/rust-lang/crates.io-index"
197
+checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
198
+
199
+[[package]]
200
+name = "rand_core"
201
+version = "0.6.4"
202
+source = "registry+https://github.com/rust-lang/crates.io-index"
203
+checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
204
+dependencies = [
205
+ "getrandom",
206
+]
207
+
208
+[[package]]
209
+name = "rustc_version"
210
+version = "0.4.1"
211
+source = "registry+https://github.com/rust-lang/crates.io-index"
212
+checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
213
+dependencies = [
214
+ "semver",
215
+]
216
+
217
+[[package]]
218
+name = "semver"
219
+version = "1.0.26"
220
+source = "registry+https://github.com/rust-lang/crates.io-index"
221
+checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0"
222
+
223
+[[package]]
224
+name = "subtle"
225
+version = "2.6.1"
226
+source = "registry+https://github.com/rust-lang/crates.io-index"
227
+checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
228
+
229
+[[package]]
230
+name = "syn"
231
+version = "2.0.100"
232
+source = "registry+https://github.com/rust-lang/crates.io-index"
233
+checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0"
234
+dependencies = [
235
+ "proc-macro2",
236
+ "quote",
237
+ "unicode-ident",
238
+]
239
+
240
+[[package]]
241
+name = "typenum"
242
+version = "1.18.0"
243
+source = "registry+https://github.com/rust-lang/crates.io-index"
244
+checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
245
+
246
+[[package]]
247
+name = "unicode-ident"
248
+version = "1.0.18"
249
+source = "registry+https://github.com/rust-lang/crates.io-index"
250
+checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
251
+
252
+[[package]]
253
+name = "version_check"
254
+version = "0.9.5"
255
+source = "registry+https://github.com/rust-lang/crates.io-index"
256
+checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
257
+
258
+[[package]]
259
+name = "wasi"
260
+version = "0.11.0+wasi-snapshot-preview1"
261
+source = "registry+https://github.com/rust-lang/crates.io-index"
262
+checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
263
+
264
+[[package]]
265
+name = "zerocopy"
266
+version = "0.8.24"
267
+source = "registry+https://github.com/rust-lang/crates.io-index"
268
+checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879"
269
+dependencies = [
270
+ "zerocopy-derive",
271
+]
272
+
273
+[[package]]
274
+name = "zerocopy-derive"
275
+version = "0.8.24"
276
+source = "registry+https://github.com/rust-lang/crates.io-index"
277
+checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be"
278
+dependencies = [
279
+ "proc-macro2",
280
+ "quote",
281
+ "syn",
282
+]
283
+
284
+[[package]]
285
+name = "zeroize"
286
+version = "1.8.1"
287
+source = "registry+https://github.com/rust-lang/crates.io-index"
288
+checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"

+ 14
- 0
Cargo.toml View File

@@ -0,0 +1,14 @@
1
+[package]
2
+name = "apet_ex1"
3
+version = "0.1.0"
4
+edition = "2024"
5
+
6
+[features]
7
+stdout=[]
8
+
9
+[dependencies]
10
+curve25519-dalek = { version = "4.1.3", features = ["rand_core", "digest"] }
11
+rand = "0.8.5"
12
+rand_core = "0.4"
13
+num-bigint = "0.4"
14
+num-traits = "0.2"

+ 149
- 0
src/circuit.rs View File

@@ -0,0 +1,149 @@
1
+use std::collections::HashMap;
2
+
3
+use crate::{gate::Gate, gate_type::GateType};
4
+
5
+
6
+#[derive(Debug, Clone)]
7
+pub struct Circuit {
8
+    pub input_bits: Vec<bool>, // Input wires
9
+    pub gates: Vec<Gate>,      // All gates
10
+}
11
+
12
+impl Circuit {
13
+    pub fn eval(self) -> bool {
14
+        let mut evaluated_gates = vec!();
15
+
16
+        for gate in self.gates {
17
+            let result = gate.eval(&self.input_bits, &evaluated_gates);
18
+            evaluated_gates.push(result);
19
+        }
20
+
21
+        match evaluated_gates.pop() {
22
+            Some(result) => result,
23
+            None => panic!("Bruh moment")
24
+        } 
25
+    }
26
+
27
+    /*
28
+        This method should create a circuit that outputs 1 if the first number A (encoded in the first n
29
+        bits) is greater than the second number B (encoded in the next n bits) .
30
+    */
31
+    pub fn compare_n_bit_numbers(input_bits: Vec<bool>, n: usize) -> Self {
32
+        if input_bits.len() < 2*n {
33
+            panic!("Expected input_bits to be of at least length {}, but it was {}", 2*n, input_bits.len())
34
+        }
35
+
36
+        /*
37
+            base case n=1: 1-bit: 
38
+            
39
+                A B | A > B
40
+                -----------
41
+                0 0 |   0
42
+                0 1 |   0
43
+                1 0 |   1
44
+                1 1 |   0
45
+
46
+            n+1 case: 2-bit:
47
+
48
+                A1 A0  B1 B0  | A > B | (A1 > B1) || ((A1 == B1) && (A0 > B0))
49
+                ----------------------|------------------------------------
50
+                0  0   0  0   |   0   |            0
51
+                0  0   0  1   |   0   |            0
52
+                0  0   1  0   |   0   |            0
53
+                0  0   1  1   |   0   |            0
54
+                0  1   0  0   |   1   |            1
55
+                0  1   0  1   |   0   |            0
56
+                0  1   1  0   |   0   |            0
57
+                0  1   1  1   |   1   |            1
58
+                1  0   0  0   |   1   |            1
59
+                1  0   0  1   |   1   |            1
60
+                1  0   1  0   |   0   |            0
61
+                1  0   1  1   |   0   |            0
62
+                1  1   0  0   |   1   |            1
63
+                1  1   0  1   |   1   |            1
64
+                1  1   1  0   |   1   |            1
65
+                1  1   1  1   |   0   |            0
66
+
67
+            The inductive pattern should become apparent now. 
68
+            For illustration here's the case for n=4, which should show the 
69
+            recursive characteristics of the formula. 
70
+
71
+            (A3 > B3) || 
72
+            ((A3 == B3) && (A2 > B2)) || 
73
+            ((A3 == B3) && (A2 == B2) && (A1 > B1)) ||
74
+            ((A3 == B3) && (A2 == B2) && (A1 == B1)) && (A0 > B0))
75
+
76
+        */
77
+
78
+        let gates = create_n_bit_comparator_gates(n);
79
+        return Circuit { input_bits, gates }
80
+    }
81
+}
82
+
83
+
84
+fn create_n_bit_comparator_gates(n: usize) -> Vec<Gate>{
85
+    let mut indices = HashMap::<String, usize>::new();
86
+    let mut all_gates: Vec<Gate> = vec!();
87
+    let mut and_gate_indices: Vec<usize> = vec!();
88
+    
89
+    rec_n_bit_comperator_gates(0, n, &mut all_gates, &mut and_gate_indices, &mut indices, );
90
+
91
+    // the OR spanning all ANDs
92
+    let or_gate = Gate::new( GateType::Or, and_gate_indices, vec!());
93
+    
94
+    all_gates.push(or_gate);
95
+
96
+    return all_gates;
97
+}
98
+
99
+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>){
100
+    // Incrementing gate index
101
+    let a_curr_gt_b_curr_gate_index = all_gates.len();
102
+
103
+    // Gate(A_current > B_current)
104
+    let a_curr_gt_b_curr_gate = Gate::new(GateType::Bigger, vec!(), vec!(curr, curr+max));
105
+
106
+    // A_current>B_current
107
+    //print!("   ( ({}) ", format!("{} > {}", format!("A{}", max-1-curr), format!("B{}", max-1-curr)));
108
+
109
+    all_gates.push(a_curr_gt_b_curr_gate);
110
+
111
+    let mut this_recursion_gate_indices: Vec<usize> = vec!(a_curr_gt_b_curr_gate_index);
112
+
113
+    for i in 0..curr {
114
+        // A_i
115
+        let a_i = format!("A{}", max-1-i);
116
+        //B_i
117
+        let b_i = format!("B{}", max-1-i);
118
+
119
+        // A_i=B_i
120
+        let a_i_eq_b_i = format!("{} = {}", a_i, b_i);
121
+        // The curr-1'th equality gate is the only one that doesn't exist yet
122
+        if i == curr-1 {
123
+            // Gate(A_current > B_current)
124
+            let a_i_eq_b_i_gate = Gate::new(GateType::Equal, vec!(), vec!(i, i+max));
125
+            let a_curr_gt_b_curr_gate_index = all_gates.len();
126
+            indices.insert(a_i_eq_b_i.clone(), a_curr_gt_b_curr_gate_index);
127
+            all_gates.push(a_i_eq_b_i_gate);
128
+        }
129
+        let eq_gate_index = indices.get(&a_i_eq_b_i).unwrap();
130
+
131
+        //print!("&& ({}) ", a_i_eq_b_i);
132
+
133
+        // Index of this equality gate
134
+        this_recursion_gate_indices.push(*eq_gate_index);
135
+    }
136
+
137
+    let and_curr_index = all_gates.len(); 
138
+    let and_curr_gate = Gate::new(GateType::And, this_recursion_gate_indices, vec!());
139
+
140
+    all_gates.push(and_curr_gate);
141
+    and_gate_incides.push(and_curr_index);
142
+
143
+    if curr+1 == max {
144
+        //println!(")");
145
+        return;
146
+    }
147
+    //println!(") ||");
148
+    return rec_n_bit_comperator_gates(curr+1, max, all_gates, and_gate_incides, indices);
149
+}

+ 122
- 0
src/gate.rs View File

@@ -0,0 +1,122 @@
1
+use crate::gate_type::GateType;
2
+
3
+#[derive(Debug, Clone)]
4
+pub struct Gate {
5
+    pub gate_type: GateType,
6
+    pub input_gates_indices: Vec<usize>, // Which previous gates to use
7
+    pub input_bits_indices: Vec<usize>,  // Which input bits to use
8
+}
9
+
10
+impl Gate {
11
+    pub fn new(
12
+        gate_type: GateType,
13
+        input_gates_indices: Vec<usize>,
14
+        input_bits_indices: Vec<usize>,
15
+    ) -> Self {
16
+        let num_input_wires = input_bits_indices.len() + input_gates_indices.len();
17
+
18
+        if num_input_wires == 0 {
19
+            panic!("A gate without inputs is invalid");
20
+        }
21
+
22
+        if gate_type == GateType::Bigger && num_input_wires != 2 {
23
+            if num_input_wires != 2 {
24
+                panic!("Bigger gates need exactly two inputs")
25
+            }
26
+        }
27
+
28
+        if gate_type == GateType::Equal && num_input_wires != 2 {
29
+            if num_input_wires != 2 {
30
+                panic!("Equal gates need exactly two inputs")
31
+            }
32
+        }
33
+        Self {
34
+            gate_type,
35
+            input_gates_indices,
36
+            input_bits_indices,
37
+        }
38
+    }
39
+
40
+    pub fn eval(&self, input_bits: &Vec<bool>, evaluated_gates: &Vec<bool>) -> bool {
41
+        /*
42
+            The goal is to perform short-circuit evaluation with the minimum number of vector lookups.
43
+        */
44
+
45
+        match self.gate_type {
46
+            /*
47
+                A multi-input gate that outputs 1 if all input bits are 1, and 0 otherwise
48
+            */
49
+            GateType::And => {
50
+
51
+                for &index in self.input_bits_indices.iter(){
52
+                    if !input_bits[index] {
53
+                        return false;
54
+                    }
55
+                }
56
+                for &index in self.input_gates_indices.iter(){
57
+                    if !evaluated_gates[index] {
58
+                        return false;
59
+                    }
60
+                }
61
+
62
+                return true;
63
+            }
64
+
65
+            /*
66
+                A multi-input gate that outputs 1 if at least one input bit is 1, and 0 otherwise.   
67
+            */
68
+            GateType::Or => {
69
+                for &index in self.input_bits_indices.iter(){
70
+                    if input_bits[index] {
71
+                        return true;
72
+                    }
73
+                }
74
+                for &index in self.input_gates_indices.iter(){
75
+                    if evaluated_gates[index] {
76
+                        return true;
77
+                    }
78
+                }
79
+                return false;
80
+            },
81
+
82
+            /*
83
+                A gate with exactly two inputs. It outputs 1 if the two input bits are equal 
84
+                (i.e., both 0 or both 1), and 0 otherwise
85
+            */            
86
+            GateType::Equal => match self.input_bits_indices.len() {
87
+                0 => evaluated_gates[self.input_gates_indices[0]] == evaluated_gates[self.input_gates_indices[1]],
88
+                1 => input_bits[self.input_bits_indices[0]] == evaluated_gates[self.input_gates_indices[0]],
89
+                2 => {
90
+                    input_bits[self.input_bits_indices[0]] == input_bits[self.input_bits_indices[1]]
91
+                },
92
+                _ => panic!{"How'd we get here?"}
93
+            },
94
+
95
+            /*
96
+                A gate with exactly two inputs. It outputs 1 if the first input is 1 and the second
97
+                input is 0; otherwise, it outputs 0. This gate is used to compare individual bits a_i > b_i
98
+
99
+                A B | A > B | A && !B
100
+                --------------------
101
+                0 0 |   0   | 0 0  1
102
+                0 1 |   0   | 0 0  0
103
+                1 0 |   1   | 1 1  1
104
+                1 1 |   0   | 1 0  0
105
+            */
106
+            GateType::Bigger => match self.input_bits_indices.len() {
107
+                // bits: [] gates: [A,B]
108
+                0 => evaluated_gates[self.input_gates_indices[0]] && !evaluated_gates[self.input_gates_indices[1]],
109
+                
110
+                // bits: [A] gates: [B]
111
+                1 => input_bits[self.input_bits_indices[0]] && !evaluated_gates[self.input_gates_indices[0]],
112
+                
113
+                // bits: [A,B] gates: []
114
+                2 => {
115
+                    input_bits[self.input_bits_indices[0]] && !input_bits[self.input_bits_indices[1]]
116
+                },
117
+
118
+                _ => panic!{"How'd we get here? {}", input_bits.len()}
119
+            },
120
+        }
121
+    }
122
+}

+ 7
- 0
src/gate_type.rs View File

@@ -0,0 +1,7 @@
1
+#[derive(Debug, Clone, PartialEq)]
2
+pub enum GateType {
3
+    And,    // multi-input
4
+    Or,     // multi-input
5
+    Equal,  // 2-input
6
+    Bigger, // 2-input (A > B)
7
+}

+ 4
- 0
src/lib.rs View File

@@ -0,0 +1,4 @@
1
+pub mod circuit;
2
+pub mod gate;
3
+pub mod gate_type;
4
+pub mod scalar_to_bits;

+ 26
- 0
src/main.rs View File

@@ -0,0 +1,26 @@
1
+use apet_ex1::{circuit::Circuit, scalar_to_bits::scalar_to_bits};
2
+use curve25519_dalek::Scalar;
3
+use num_bigint::BigUint;
4
+use rand::rngs::OsRng;
5
+
6
+fn main() {
7
+    let a = Scalar::random(&mut OsRng);
8
+    let b = Scalar::random(&mut OsRng);
9
+    // Convert to bit representation
10
+    let a_bits = scalar_to_bits(&a);
11
+    let b_bits = scalar_to_bits(&b);
12
+
13
+    // Combine A and B bits into one input vector
14
+    let mut input_bits = Vec::with_capacity(512);
15
+    input_bits.extend_from_slice(&a_bits);
16
+    input_bits.extend_from_slice(&b_bits);
17
+
18
+    // Build and evaluate the comparison circuit
19
+    let circuit = Circuit::compare_n_bit_numbers(input_bits, 256);
20
+    let circuit_result = circuit.eval();
21
+
22
+    let a_int = BigUint::from_bytes_le(&a.to_bytes());
23
+    let b_int = BigUint::from_bytes_le(&b.to_bytes());
24
+
25
+    println!("{}", circuit_result == (a_int > b_int))
26
+}

+ 16
- 0
src/scalar_to_bits.rs View File

@@ -0,0 +1,16 @@
1
+use curve25519_dalek::Scalar;
2
+
3
+pub fn scalar_to_bits(scalar: &Scalar) -> Vec<bool> {
4
+    let bytes = scalar.to_bytes();
5
+    let mut bits = Vec::with_capacity(256);
6
+
7
+    // MSB first
8
+    for &byte in bytes.iter().rev() {
9
+        for i in (0..8).rev() {
10
+            let bit = (byte >> i) & 1;
11
+            bits.push(bit != 0);
12
+        }
13
+    }
14
+
15
+    bits
16
+}

+ 38
- 0
tests/test.rs View File

@@ -0,0 +1,38 @@
1
+#[cfg(test)]
2
+mod tests {
3
+    use apet_ex1::{circuit::Circuit, scalar_to_bits::scalar_to_bits};
4
+    use curve25519_dalek::scalar::Scalar;
5
+    use num_bigint::BigUint;
6
+    use rand::rngs::OsRng;
7
+    #[test]
8
+    fn test_scalar_comparison_via_circuit() {
9
+        for _ in 0..100 {
10
+            let a = Scalar::random(&mut OsRng);
11
+            let b = Scalar::random(&mut OsRng);
12
+
13
+            // Convert to bit representation
14
+            let a_bits = scalar_to_bits(&a);
15
+            let b_bits = scalar_to_bits(&b);
16
+
17
+            // Combine A and B bits into one input vector
18
+            let mut input_bits = Vec::with_capacity(512);
19
+            input_bits.extend_from_slice(&a_bits);
20
+            input_bits.extend_from_slice(&b_bits);
21
+
22
+            // Build and evaluate the comparison circuit
23
+            let circuit = Circuit::compare_n_bit_numbers(input_bits, 256);
24
+            let circuit_result = circuit.eval();
25
+
26
+            // Compare expected result using BigUint
27
+            let a_int = BigUint::from_bytes_le(&a.to_bytes());
28
+            let b_int = BigUint::from_bytes_le(&b.to_bytes());
29
+            let expected = a_int > b_int;
30
+
31
+            assert_eq!(
32
+                circuit_result, expected,
33
+                "Mismatch: A = {:?}, B = {:?}, A > B = {}, but circuit says {}",
34
+                a_int, b_int, expected, circuit_result
35
+            );
36
+        }
37
+    }
38
+}

Loading…
Cancel
Save