@izi-noir/sdk 0.1.12 → 0.1.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +102 -6
- package/dist/index.d.cts +26 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.js +102 -6
- package/dist/providers/arkworks.cjs +102 -6
- package/dist/providers/arkworks.js +102 -6
- package/dist/providers/barretenberg.cjs +102 -6
- package/dist/providers/barretenberg.js +102 -6
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -146,6 +146,8 @@ var init_R1csBuilder = __esm({
|
|
|
146
146
|
// Fr modulus = 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001
|
|
147
147
|
// -1 mod Fr = Fr - 1
|
|
148
148
|
NEG_ONE = "0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000";
|
|
149
|
+
// Number of bits for range checks (64 bits handles values up to ~18 quintillion)
|
|
150
|
+
COMPARISON_BITS = 64;
|
|
149
151
|
/**
|
|
150
152
|
* Build R1CS definition from the parsed circuit
|
|
151
153
|
*/
|
|
@@ -255,13 +257,18 @@ var init_R1csBuilder = __esm({
|
|
|
255
257
|
throw new Error(
|
|
256
258
|
`Arithmetic operator ${operator} must be part of an equality assertion. Use: assert(a ${operator} b == c)`
|
|
257
259
|
);
|
|
258
|
-
case "
|
|
260
|
+
case ">=":
|
|
261
|
+
this.processGreaterThanOrEqual(left, right);
|
|
262
|
+
break;
|
|
259
263
|
case ">":
|
|
264
|
+
this.processGreaterThan(left, right);
|
|
265
|
+
break;
|
|
260
266
|
case "<=":
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
);
|
|
267
|
+
this.processGreaterThanOrEqual(right, left);
|
|
268
|
+
break;
|
|
269
|
+
case "<":
|
|
270
|
+
this.processGreaterThan(right, left);
|
|
271
|
+
break;
|
|
265
272
|
case "&":
|
|
266
273
|
case "|":
|
|
267
274
|
throw new Error(
|
|
@@ -368,6 +375,83 @@ var init_R1csBuilder = __esm({
|
|
|
368
375
|
// = c
|
|
369
376
|
});
|
|
370
377
|
}
|
|
378
|
+
/**
|
|
379
|
+
* Process greater than or equal: assert(a >= b)
|
|
380
|
+
* Uses bit decomposition to prove that a - b is non-negative.
|
|
381
|
+
*
|
|
382
|
+
* The approach:
|
|
383
|
+
* 1. Create diff = a - b
|
|
384
|
+
* 2. Decompose diff into COMPARISON_BITS bits
|
|
385
|
+
* 3. For each bit: bit_i * (1 - bit_i) = 0 (ensures 0 or 1)
|
|
386
|
+
* 4. Sum of bits * powers of 2 = diff
|
|
387
|
+
*
|
|
388
|
+
* If decomposition succeeds, diff is in [0, 2^COMPARISON_BITS - 1], so a >= b
|
|
389
|
+
*/
|
|
390
|
+
processGreaterThanOrEqual(left, right) {
|
|
391
|
+
const leftIdx = this.getOrCreateWitness(left);
|
|
392
|
+
const rightIdx = this.getOrCreateWitness(right);
|
|
393
|
+
const diffIdx = this.nextWitnessIdx++;
|
|
394
|
+
this.constraints.push({
|
|
395
|
+
a: [
|
|
396
|
+
["0x1", leftIdx],
|
|
397
|
+
[this.NEG_ONE, rightIdx]
|
|
398
|
+
],
|
|
399
|
+
b: [["0x1", 0]],
|
|
400
|
+
// * 1
|
|
401
|
+
c: [["0x1", diffIdx]]
|
|
402
|
+
});
|
|
403
|
+
this.addBitDecompositionConstraints(diffIdx);
|
|
404
|
+
}
|
|
405
|
+
/**
|
|
406
|
+
* Process greater than: assert(a > b)
|
|
407
|
+
* Equivalent to assert(a - b - 1 >= 0), or assert(a >= b + 1)
|
|
408
|
+
*/
|
|
409
|
+
processGreaterThan(left, right) {
|
|
410
|
+
const leftIdx = this.getOrCreateWitness(left);
|
|
411
|
+
const rightIdx = this.getOrCreateWitness(right);
|
|
412
|
+
const diffIdx = this.nextWitnessIdx++;
|
|
413
|
+
this.constraints.push({
|
|
414
|
+
a: [
|
|
415
|
+
["0x1", leftIdx],
|
|
416
|
+
[this.NEG_ONE, rightIdx],
|
|
417
|
+
[this.NEG_ONE, 0]
|
|
418
|
+
// -1 (using w_0 = 1)
|
|
419
|
+
],
|
|
420
|
+
b: [["0x1", 0]],
|
|
421
|
+
// * 1
|
|
422
|
+
c: [["0x1", diffIdx]]
|
|
423
|
+
});
|
|
424
|
+
this.addBitDecompositionConstraints(diffIdx);
|
|
425
|
+
}
|
|
426
|
+
/**
|
|
427
|
+
* Add bit decomposition constraints for a value.
|
|
428
|
+
* Creates COMPARISON_BITS witnesses for the bits and constrains:
|
|
429
|
+
* 1. Each bit is 0 or 1: bit * (1 - bit) = 0
|
|
430
|
+
* 2. Sum of bits * 2^i = value
|
|
431
|
+
*/
|
|
432
|
+
addBitDecompositionConstraints(valueIdx) {
|
|
433
|
+
const bitIndices = [];
|
|
434
|
+
for (let i = 0; i < this.COMPARISON_BITS; i++) {
|
|
435
|
+
const bitIdx = this.nextWitnessIdx++;
|
|
436
|
+
bitIndices.push(bitIdx);
|
|
437
|
+
this.constraints.push({
|
|
438
|
+
a: [["0x1", bitIdx]],
|
|
439
|
+
b: [["0x1", bitIdx]],
|
|
440
|
+
c: [["0x1", bitIdx]]
|
|
441
|
+
});
|
|
442
|
+
}
|
|
443
|
+
const sumTerms = [];
|
|
444
|
+
for (let i = 0; i < this.COMPARISON_BITS; i++) {
|
|
445
|
+
const coeff = (1n << BigInt(i)).toString(16);
|
|
446
|
+
sumTerms.push([`0x${coeff}`, bitIndices[i]]);
|
|
447
|
+
}
|
|
448
|
+
this.constraints.push({
|
|
449
|
+
a: sumTerms,
|
|
450
|
+
b: [["0x1", 0]],
|
|
451
|
+
// * 1
|
|
452
|
+
c: [["0x1", valueIdx]]
|
|
453
|
+
});
|
|
454
|
+
}
|
|
371
455
|
/**
|
|
372
456
|
* Process a variable declaration: let x = expr
|
|
373
457
|
* Creates a new witness for x and adds constraint if needed
|
|
@@ -709,7 +793,19 @@ authors = [""]
|
|
|
709
793
|
private_inputs: privateR1csIndices,
|
|
710
794
|
constraints: []
|
|
711
795
|
};
|
|
712
|
-
if (privateR1csIndices.length ===
|
|
796
|
+
if (privateR1csIndices.length === 2 && publicR1csIndices.length === 1) {
|
|
797
|
+
const aIdx = privateR1csIndices[0];
|
|
798
|
+
const bIdx = privateR1csIndices[1];
|
|
799
|
+
const totalIdx = publicR1csIndices[0];
|
|
800
|
+
r1cs.constraints.push({
|
|
801
|
+
a: [["0x1", aIdx], ["0x1", bIdx]],
|
|
802
|
+
// a + b
|
|
803
|
+
b: [["0x1", 0]],
|
|
804
|
+
// * 1 (w_0 = 1)
|
|
805
|
+
c: [["0x1", totalIdx]]
|
|
806
|
+
// = total
|
|
807
|
+
});
|
|
808
|
+
} else if (privateR1csIndices.length === 1 && publicR1csIndices.length === 1) {
|
|
713
809
|
const privateIdx = privateR1csIndices[0];
|
|
714
810
|
const publicIdx = publicR1csIndices[0];
|
|
715
811
|
r1cs.constraints.push({
|
package/dist/index.d.cts
CHANGED
|
@@ -108,6 +108,7 @@ declare class R1csBuilder {
|
|
|
108
108
|
private publicIndices;
|
|
109
109
|
private privateIndices;
|
|
110
110
|
private readonly NEG_ONE;
|
|
111
|
+
private readonly COMPARISON_BITS;
|
|
111
112
|
constructor(parsedCircuit: ParsedCircuit);
|
|
112
113
|
/**
|
|
113
114
|
* Build R1CS definition from the parsed circuit
|
|
@@ -156,6 +157,31 @@ declare class R1csBuilder {
|
|
|
156
157
|
* R1CS: (a - b) * 1 = c
|
|
157
158
|
*/
|
|
158
159
|
private processSubtractionEquality;
|
|
160
|
+
/**
|
|
161
|
+
* Process greater than or equal: assert(a >= b)
|
|
162
|
+
* Uses bit decomposition to prove that a - b is non-negative.
|
|
163
|
+
*
|
|
164
|
+
* The approach:
|
|
165
|
+
* 1. Create diff = a - b
|
|
166
|
+
* 2. Decompose diff into COMPARISON_BITS bits
|
|
167
|
+
* 3. For each bit: bit_i * (1 - bit_i) = 0 (ensures 0 or 1)
|
|
168
|
+
* 4. Sum of bits * powers of 2 = diff
|
|
169
|
+
*
|
|
170
|
+
* If decomposition succeeds, diff is in [0, 2^COMPARISON_BITS - 1], so a >= b
|
|
171
|
+
*/
|
|
172
|
+
private processGreaterThanOrEqual;
|
|
173
|
+
/**
|
|
174
|
+
* Process greater than: assert(a > b)
|
|
175
|
+
* Equivalent to assert(a - b - 1 >= 0), or assert(a >= b + 1)
|
|
176
|
+
*/
|
|
177
|
+
private processGreaterThan;
|
|
178
|
+
/**
|
|
179
|
+
* Add bit decomposition constraints for a value.
|
|
180
|
+
* Creates COMPARISON_BITS witnesses for the bits and constrains:
|
|
181
|
+
* 1. Each bit is 0 or 1: bit * (1 - bit) = 0
|
|
182
|
+
* 2. Sum of bits * 2^i = value
|
|
183
|
+
*/
|
|
184
|
+
private addBitDecompositionConstraints;
|
|
159
185
|
/**
|
|
160
186
|
* Process a variable declaration: let x = expr
|
|
161
187
|
* Creates a new witness for x and adds constraint if needed
|
package/dist/index.d.ts
CHANGED
|
@@ -108,6 +108,7 @@ declare class R1csBuilder {
|
|
|
108
108
|
private publicIndices;
|
|
109
109
|
private privateIndices;
|
|
110
110
|
private readonly NEG_ONE;
|
|
111
|
+
private readonly COMPARISON_BITS;
|
|
111
112
|
constructor(parsedCircuit: ParsedCircuit);
|
|
112
113
|
/**
|
|
113
114
|
* Build R1CS definition from the parsed circuit
|
|
@@ -156,6 +157,31 @@ declare class R1csBuilder {
|
|
|
156
157
|
* R1CS: (a - b) * 1 = c
|
|
157
158
|
*/
|
|
158
159
|
private processSubtractionEquality;
|
|
160
|
+
/**
|
|
161
|
+
* Process greater than or equal: assert(a >= b)
|
|
162
|
+
* Uses bit decomposition to prove that a - b is non-negative.
|
|
163
|
+
*
|
|
164
|
+
* The approach:
|
|
165
|
+
* 1. Create diff = a - b
|
|
166
|
+
* 2. Decompose diff into COMPARISON_BITS bits
|
|
167
|
+
* 3. For each bit: bit_i * (1 - bit_i) = 0 (ensures 0 or 1)
|
|
168
|
+
* 4. Sum of bits * powers of 2 = diff
|
|
169
|
+
*
|
|
170
|
+
* If decomposition succeeds, diff is in [0, 2^COMPARISON_BITS - 1], so a >= b
|
|
171
|
+
*/
|
|
172
|
+
private processGreaterThanOrEqual;
|
|
173
|
+
/**
|
|
174
|
+
* Process greater than: assert(a > b)
|
|
175
|
+
* Equivalent to assert(a - b - 1 >= 0), or assert(a >= b + 1)
|
|
176
|
+
*/
|
|
177
|
+
private processGreaterThan;
|
|
178
|
+
/**
|
|
179
|
+
* Add bit decomposition constraints for a value.
|
|
180
|
+
* Creates COMPARISON_BITS witnesses for the bits and constrains:
|
|
181
|
+
* 1. Each bit is 0 or 1: bit * (1 - bit) = 0
|
|
182
|
+
* 2. Sum of bits * 2^i = value
|
|
183
|
+
*/
|
|
184
|
+
private addBitDecompositionConstraints;
|
|
159
185
|
/**
|
|
160
186
|
* Process a variable declaration: let x = expr
|
|
161
187
|
* Creates a new witness for x and adds constraint if needed
|
package/dist/index.js
CHANGED
|
@@ -124,6 +124,8 @@ var init_R1csBuilder = __esm({
|
|
|
124
124
|
// Fr modulus = 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001
|
|
125
125
|
// -1 mod Fr = Fr - 1
|
|
126
126
|
NEG_ONE = "0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000";
|
|
127
|
+
// Number of bits for range checks (64 bits handles values up to ~18 quintillion)
|
|
128
|
+
COMPARISON_BITS = 64;
|
|
127
129
|
/**
|
|
128
130
|
* Build R1CS definition from the parsed circuit
|
|
129
131
|
*/
|
|
@@ -233,13 +235,18 @@ var init_R1csBuilder = __esm({
|
|
|
233
235
|
throw new Error(
|
|
234
236
|
`Arithmetic operator ${operator} must be part of an equality assertion. Use: assert(a ${operator} b == c)`
|
|
235
237
|
);
|
|
236
|
-
case "
|
|
238
|
+
case ">=":
|
|
239
|
+
this.processGreaterThanOrEqual(left, right);
|
|
240
|
+
break;
|
|
237
241
|
case ">":
|
|
242
|
+
this.processGreaterThan(left, right);
|
|
243
|
+
break;
|
|
238
244
|
case "<=":
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
);
|
|
245
|
+
this.processGreaterThanOrEqual(right, left);
|
|
246
|
+
break;
|
|
247
|
+
case "<":
|
|
248
|
+
this.processGreaterThan(right, left);
|
|
249
|
+
break;
|
|
243
250
|
case "&":
|
|
244
251
|
case "|":
|
|
245
252
|
throw new Error(
|
|
@@ -346,6 +353,83 @@ var init_R1csBuilder = __esm({
|
|
|
346
353
|
// = c
|
|
347
354
|
});
|
|
348
355
|
}
|
|
356
|
+
/**
|
|
357
|
+
* Process greater than or equal: assert(a >= b)
|
|
358
|
+
* Uses bit decomposition to prove that a - b is non-negative.
|
|
359
|
+
*
|
|
360
|
+
* The approach:
|
|
361
|
+
* 1. Create diff = a - b
|
|
362
|
+
* 2. Decompose diff into COMPARISON_BITS bits
|
|
363
|
+
* 3. For each bit: bit_i * (1 - bit_i) = 0 (ensures 0 or 1)
|
|
364
|
+
* 4. Sum of bits * powers of 2 = diff
|
|
365
|
+
*
|
|
366
|
+
* If decomposition succeeds, diff is in [0, 2^COMPARISON_BITS - 1], so a >= b
|
|
367
|
+
*/
|
|
368
|
+
processGreaterThanOrEqual(left, right) {
|
|
369
|
+
const leftIdx = this.getOrCreateWitness(left);
|
|
370
|
+
const rightIdx = this.getOrCreateWitness(right);
|
|
371
|
+
const diffIdx = this.nextWitnessIdx++;
|
|
372
|
+
this.constraints.push({
|
|
373
|
+
a: [
|
|
374
|
+
["0x1", leftIdx],
|
|
375
|
+
[this.NEG_ONE, rightIdx]
|
|
376
|
+
],
|
|
377
|
+
b: [["0x1", 0]],
|
|
378
|
+
// * 1
|
|
379
|
+
c: [["0x1", diffIdx]]
|
|
380
|
+
});
|
|
381
|
+
this.addBitDecompositionConstraints(diffIdx);
|
|
382
|
+
}
|
|
383
|
+
/**
|
|
384
|
+
* Process greater than: assert(a > b)
|
|
385
|
+
* Equivalent to assert(a - b - 1 >= 0), or assert(a >= b + 1)
|
|
386
|
+
*/
|
|
387
|
+
processGreaterThan(left, right) {
|
|
388
|
+
const leftIdx = this.getOrCreateWitness(left);
|
|
389
|
+
const rightIdx = this.getOrCreateWitness(right);
|
|
390
|
+
const diffIdx = this.nextWitnessIdx++;
|
|
391
|
+
this.constraints.push({
|
|
392
|
+
a: [
|
|
393
|
+
["0x1", leftIdx],
|
|
394
|
+
[this.NEG_ONE, rightIdx],
|
|
395
|
+
[this.NEG_ONE, 0]
|
|
396
|
+
// -1 (using w_0 = 1)
|
|
397
|
+
],
|
|
398
|
+
b: [["0x1", 0]],
|
|
399
|
+
// * 1
|
|
400
|
+
c: [["0x1", diffIdx]]
|
|
401
|
+
});
|
|
402
|
+
this.addBitDecompositionConstraints(diffIdx);
|
|
403
|
+
}
|
|
404
|
+
/**
|
|
405
|
+
* Add bit decomposition constraints for a value.
|
|
406
|
+
* Creates COMPARISON_BITS witnesses for the bits and constrains:
|
|
407
|
+
* 1. Each bit is 0 or 1: bit * (1 - bit) = 0
|
|
408
|
+
* 2. Sum of bits * 2^i = value
|
|
409
|
+
*/
|
|
410
|
+
addBitDecompositionConstraints(valueIdx) {
|
|
411
|
+
const bitIndices = [];
|
|
412
|
+
for (let i = 0; i < this.COMPARISON_BITS; i++) {
|
|
413
|
+
const bitIdx = this.nextWitnessIdx++;
|
|
414
|
+
bitIndices.push(bitIdx);
|
|
415
|
+
this.constraints.push({
|
|
416
|
+
a: [["0x1", bitIdx]],
|
|
417
|
+
b: [["0x1", bitIdx]],
|
|
418
|
+
c: [["0x1", bitIdx]]
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
const sumTerms = [];
|
|
422
|
+
for (let i = 0; i < this.COMPARISON_BITS; i++) {
|
|
423
|
+
const coeff = (1n << BigInt(i)).toString(16);
|
|
424
|
+
sumTerms.push([`0x${coeff}`, bitIndices[i]]);
|
|
425
|
+
}
|
|
426
|
+
this.constraints.push({
|
|
427
|
+
a: sumTerms,
|
|
428
|
+
b: [["0x1", 0]],
|
|
429
|
+
// * 1
|
|
430
|
+
c: [["0x1", valueIdx]]
|
|
431
|
+
});
|
|
432
|
+
}
|
|
349
433
|
/**
|
|
350
434
|
* Process a variable declaration: let x = expr
|
|
351
435
|
* Creates a new witness for x and adds constraint if needed
|
|
@@ -686,7 +770,19 @@ authors = [""]
|
|
|
686
770
|
private_inputs: privateR1csIndices,
|
|
687
771
|
constraints: []
|
|
688
772
|
};
|
|
689
|
-
if (privateR1csIndices.length ===
|
|
773
|
+
if (privateR1csIndices.length === 2 && publicR1csIndices.length === 1) {
|
|
774
|
+
const aIdx = privateR1csIndices[0];
|
|
775
|
+
const bIdx = privateR1csIndices[1];
|
|
776
|
+
const totalIdx = publicR1csIndices[0];
|
|
777
|
+
r1cs.constraints.push({
|
|
778
|
+
a: [["0x1", aIdx], ["0x1", bIdx]],
|
|
779
|
+
// a + b
|
|
780
|
+
b: [["0x1", 0]],
|
|
781
|
+
// * 1 (w_0 = 1)
|
|
782
|
+
c: [["0x1", totalIdx]]
|
|
783
|
+
// = total
|
|
784
|
+
});
|
|
785
|
+
} else if (privateR1csIndices.length === 1 && publicR1csIndices.length === 1) {
|
|
690
786
|
const privateIdx = privateR1csIndices[0];
|
|
691
787
|
const publicIdx = publicR1csIndices[0];
|
|
692
788
|
r1cs.constraints.push({
|
|
@@ -49,6 +49,8 @@ var init_R1csBuilder = __esm({
|
|
|
49
49
|
// Fr modulus = 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001
|
|
50
50
|
// -1 mod Fr = Fr - 1
|
|
51
51
|
NEG_ONE = "0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000";
|
|
52
|
+
// Number of bits for range checks (64 bits handles values up to ~18 quintillion)
|
|
53
|
+
COMPARISON_BITS = 64;
|
|
52
54
|
/**
|
|
53
55
|
* Build R1CS definition from the parsed circuit
|
|
54
56
|
*/
|
|
@@ -158,13 +160,18 @@ var init_R1csBuilder = __esm({
|
|
|
158
160
|
throw new Error(
|
|
159
161
|
`Arithmetic operator ${operator} must be part of an equality assertion. Use: assert(a ${operator} b == c)`
|
|
160
162
|
);
|
|
161
|
-
case "
|
|
163
|
+
case ">=":
|
|
164
|
+
this.processGreaterThanOrEqual(left, right);
|
|
165
|
+
break;
|
|
162
166
|
case ">":
|
|
167
|
+
this.processGreaterThan(left, right);
|
|
168
|
+
break;
|
|
163
169
|
case "<=":
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
);
|
|
170
|
+
this.processGreaterThanOrEqual(right, left);
|
|
171
|
+
break;
|
|
172
|
+
case "<":
|
|
173
|
+
this.processGreaterThan(right, left);
|
|
174
|
+
break;
|
|
168
175
|
case "&":
|
|
169
176
|
case "|":
|
|
170
177
|
throw new Error(
|
|
@@ -271,6 +278,83 @@ var init_R1csBuilder = __esm({
|
|
|
271
278
|
// = c
|
|
272
279
|
});
|
|
273
280
|
}
|
|
281
|
+
/**
|
|
282
|
+
* Process greater than or equal: assert(a >= b)
|
|
283
|
+
* Uses bit decomposition to prove that a - b is non-negative.
|
|
284
|
+
*
|
|
285
|
+
* The approach:
|
|
286
|
+
* 1. Create diff = a - b
|
|
287
|
+
* 2. Decompose diff into COMPARISON_BITS bits
|
|
288
|
+
* 3. For each bit: bit_i * (1 - bit_i) = 0 (ensures 0 or 1)
|
|
289
|
+
* 4. Sum of bits * powers of 2 = diff
|
|
290
|
+
*
|
|
291
|
+
* If decomposition succeeds, diff is in [0, 2^COMPARISON_BITS - 1], so a >= b
|
|
292
|
+
*/
|
|
293
|
+
processGreaterThanOrEqual(left, right) {
|
|
294
|
+
const leftIdx = this.getOrCreateWitness(left);
|
|
295
|
+
const rightIdx = this.getOrCreateWitness(right);
|
|
296
|
+
const diffIdx = this.nextWitnessIdx++;
|
|
297
|
+
this.constraints.push({
|
|
298
|
+
a: [
|
|
299
|
+
["0x1", leftIdx],
|
|
300
|
+
[this.NEG_ONE, rightIdx]
|
|
301
|
+
],
|
|
302
|
+
b: [["0x1", 0]],
|
|
303
|
+
// * 1
|
|
304
|
+
c: [["0x1", diffIdx]]
|
|
305
|
+
});
|
|
306
|
+
this.addBitDecompositionConstraints(diffIdx);
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Process greater than: assert(a > b)
|
|
310
|
+
* Equivalent to assert(a - b - 1 >= 0), or assert(a >= b + 1)
|
|
311
|
+
*/
|
|
312
|
+
processGreaterThan(left, right) {
|
|
313
|
+
const leftIdx = this.getOrCreateWitness(left);
|
|
314
|
+
const rightIdx = this.getOrCreateWitness(right);
|
|
315
|
+
const diffIdx = this.nextWitnessIdx++;
|
|
316
|
+
this.constraints.push({
|
|
317
|
+
a: [
|
|
318
|
+
["0x1", leftIdx],
|
|
319
|
+
[this.NEG_ONE, rightIdx],
|
|
320
|
+
[this.NEG_ONE, 0]
|
|
321
|
+
// -1 (using w_0 = 1)
|
|
322
|
+
],
|
|
323
|
+
b: [["0x1", 0]],
|
|
324
|
+
// * 1
|
|
325
|
+
c: [["0x1", diffIdx]]
|
|
326
|
+
});
|
|
327
|
+
this.addBitDecompositionConstraints(diffIdx);
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Add bit decomposition constraints for a value.
|
|
331
|
+
* Creates COMPARISON_BITS witnesses for the bits and constrains:
|
|
332
|
+
* 1. Each bit is 0 or 1: bit * (1 - bit) = 0
|
|
333
|
+
* 2. Sum of bits * 2^i = value
|
|
334
|
+
*/
|
|
335
|
+
addBitDecompositionConstraints(valueIdx) {
|
|
336
|
+
const bitIndices = [];
|
|
337
|
+
for (let i = 0; i < this.COMPARISON_BITS; i++) {
|
|
338
|
+
const bitIdx = this.nextWitnessIdx++;
|
|
339
|
+
bitIndices.push(bitIdx);
|
|
340
|
+
this.constraints.push({
|
|
341
|
+
a: [["0x1", bitIdx]],
|
|
342
|
+
b: [["0x1", bitIdx]],
|
|
343
|
+
c: [["0x1", bitIdx]]
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
const sumTerms = [];
|
|
347
|
+
for (let i = 0; i < this.COMPARISON_BITS; i++) {
|
|
348
|
+
const coeff = (1n << BigInt(i)).toString(16);
|
|
349
|
+
sumTerms.push([`0x${coeff}`, bitIndices[i]]);
|
|
350
|
+
}
|
|
351
|
+
this.constraints.push({
|
|
352
|
+
a: sumTerms,
|
|
353
|
+
b: [["0x1", 0]],
|
|
354
|
+
// * 1
|
|
355
|
+
c: [["0x1", valueIdx]]
|
|
356
|
+
});
|
|
357
|
+
}
|
|
274
358
|
/**
|
|
275
359
|
* Process a variable declaration: let x = expr
|
|
276
360
|
* Creates a new witness for x and adds constraint if needed
|
|
@@ -612,7 +696,19 @@ authors = [""]
|
|
|
612
696
|
private_inputs: privateR1csIndices,
|
|
613
697
|
constraints: []
|
|
614
698
|
};
|
|
615
|
-
if (privateR1csIndices.length ===
|
|
699
|
+
if (privateR1csIndices.length === 2 && publicR1csIndices.length === 1) {
|
|
700
|
+
const aIdx = privateR1csIndices[0];
|
|
701
|
+
const bIdx = privateR1csIndices[1];
|
|
702
|
+
const totalIdx = publicR1csIndices[0];
|
|
703
|
+
r1cs.constraints.push({
|
|
704
|
+
a: [["0x1", aIdx], ["0x1", bIdx]],
|
|
705
|
+
// a + b
|
|
706
|
+
b: [["0x1", 0]],
|
|
707
|
+
// * 1 (w_0 = 1)
|
|
708
|
+
c: [["0x1", totalIdx]]
|
|
709
|
+
// = total
|
|
710
|
+
});
|
|
711
|
+
} else if (privateR1csIndices.length === 1 && publicR1csIndices.length === 1) {
|
|
616
712
|
const privateIdx = privateR1csIndices[0];
|
|
617
713
|
const publicIdx = publicR1csIndices[0];
|
|
618
714
|
r1cs.constraints.push({
|
|
@@ -27,6 +27,8 @@ var init_R1csBuilder = __esm({
|
|
|
27
27
|
// Fr modulus = 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001
|
|
28
28
|
// -1 mod Fr = Fr - 1
|
|
29
29
|
NEG_ONE = "0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000";
|
|
30
|
+
// Number of bits for range checks (64 bits handles values up to ~18 quintillion)
|
|
31
|
+
COMPARISON_BITS = 64;
|
|
30
32
|
/**
|
|
31
33
|
* Build R1CS definition from the parsed circuit
|
|
32
34
|
*/
|
|
@@ -136,13 +138,18 @@ var init_R1csBuilder = __esm({
|
|
|
136
138
|
throw new Error(
|
|
137
139
|
`Arithmetic operator ${operator} must be part of an equality assertion. Use: assert(a ${operator} b == c)`
|
|
138
140
|
);
|
|
139
|
-
case "
|
|
141
|
+
case ">=":
|
|
142
|
+
this.processGreaterThanOrEqual(left, right);
|
|
143
|
+
break;
|
|
140
144
|
case ">":
|
|
145
|
+
this.processGreaterThan(left, right);
|
|
146
|
+
break;
|
|
141
147
|
case "<=":
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
);
|
|
148
|
+
this.processGreaterThanOrEqual(right, left);
|
|
149
|
+
break;
|
|
150
|
+
case "<":
|
|
151
|
+
this.processGreaterThan(right, left);
|
|
152
|
+
break;
|
|
146
153
|
case "&":
|
|
147
154
|
case "|":
|
|
148
155
|
throw new Error(
|
|
@@ -249,6 +256,83 @@ var init_R1csBuilder = __esm({
|
|
|
249
256
|
// = c
|
|
250
257
|
});
|
|
251
258
|
}
|
|
259
|
+
/**
|
|
260
|
+
* Process greater than or equal: assert(a >= b)
|
|
261
|
+
* Uses bit decomposition to prove that a - b is non-negative.
|
|
262
|
+
*
|
|
263
|
+
* The approach:
|
|
264
|
+
* 1. Create diff = a - b
|
|
265
|
+
* 2. Decompose diff into COMPARISON_BITS bits
|
|
266
|
+
* 3. For each bit: bit_i * (1 - bit_i) = 0 (ensures 0 or 1)
|
|
267
|
+
* 4. Sum of bits * powers of 2 = diff
|
|
268
|
+
*
|
|
269
|
+
* If decomposition succeeds, diff is in [0, 2^COMPARISON_BITS - 1], so a >= b
|
|
270
|
+
*/
|
|
271
|
+
processGreaterThanOrEqual(left, right) {
|
|
272
|
+
const leftIdx = this.getOrCreateWitness(left);
|
|
273
|
+
const rightIdx = this.getOrCreateWitness(right);
|
|
274
|
+
const diffIdx = this.nextWitnessIdx++;
|
|
275
|
+
this.constraints.push({
|
|
276
|
+
a: [
|
|
277
|
+
["0x1", leftIdx],
|
|
278
|
+
[this.NEG_ONE, rightIdx]
|
|
279
|
+
],
|
|
280
|
+
b: [["0x1", 0]],
|
|
281
|
+
// * 1
|
|
282
|
+
c: [["0x1", diffIdx]]
|
|
283
|
+
});
|
|
284
|
+
this.addBitDecompositionConstraints(diffIdx);
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Process greater than: assert(a > b)
|
|
288
|
+
* Equivalent to assert(a - b - 1 >= 0), or assert(a >= b + 1)
|
|
289
|
+
*/
|
|
290
|
+
processGreaterThan(left, right) {
|
|
291
|
+
const leftIdx = this.getOrCreateWitness(left);
|
|
292
|
+
const rightIdx = this.getOrCreateWitness(right);
|
|
293
|
+
const diffIdx = this.nextWitnessIdx++;
|
|
294
|
+
this.constraints.push({
|
|
295
|
+
a: [
|
|
296
|
+
["0x1", leftIdx],
|
|
297
|
+
[this.NEG_ONE, rightIdx],
|
|
298
|
+
[this.NEG_ONE, 0]
|
|
299
|
+
// -1 (using w_0 = 1)
|
|
300
|
+
],
|
|
301
|
+
b: [["0x1", 0]],
|
|
302
|
+
// * 1
|
|
303
|
+
c: [["0x1", diffIdx]]
|
|
304
|
+
});
|
|
305
|
+
this.addBitDecompositionConstraints(diffIdx);
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Add bit decomposition constraints for a value.
|
|
309
|
+
* Creates COMPARISON_BITS witnesses for the bits and constrains:
|
|
310
|
+
* 1. Each bit is 0 or 1: bit * (1 - bit) = 0
|
|
311
|
+
* 2. Sum of bits * 2^i = value
|
|
312
|
+
*/
|
|
313
|
+
addBitDecompositionConstraints(valueIdx) {
|
|
314
|
+
const bitIndices = [];
|
|
315
|
+
for (let i = 0; i < this.COMPARISON_BITS; i++) {
|
|
316
|
+
const bitIdx = this.nextWitnessIdx++;
|
|
317
|
+
bitIndices.push(bitIdx);
|
|
318
|
+
this.constraints.push({
|
|
319
|
+
a: [["0x1", bitIdx]],
|
|
320
|
+
b: [["0x1", bitIdx]],
|
|
321
|
+
c: [["0x1", bitIdx]]
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
const sumTerms = [];
|
|
325
|
+
for (let i = 0; i < this.COMPARISON_BITS; i++) {
|
|
326
|
+
const coeff = (1n << BigInt(i)).toString(16);
|
|
327
|
+
sumTerms.push([`0x${coeff}`, bitIndices[i]]);
|
|
328
|
+
}
|
|
329
|
+
this.constraints.push({
|
|
330
|
+
a: sumTerms,
|
|
331
|
+
b: [["0x1", 0]],
|
|
332
|
+
// * 1
|
|
333
|
+
c: [["0x1", valueIdx]]
|
|
334
|
+
});
|
|
335
|
+
}
|
|
252
336
|
/**
|
|
253
337
|
* Process a variable declaration: let x = expr
|
|
254
338
|
* Creates a new witness for x and adds constraint if needed
|
|
@@ -589,7 +673,19 @@ authors = [""]
|
|
|
589
673
|
private_inputs: privateR1csIndices,
|
|
590
674
|
constraints: []
|
|
591
675
|
};
|
|
592
|
-
if (privateR1csIndices.length ===
|
|
676
|
+
if (privateR1csIndices.length === 2 && publicR1csIndices.length === 1) {
|
|
677
|
+
const aIdx = privateR1csIndices[0];
|
|
678
|
+
const bIdx = privateR1csIndices[1];
|
|
679
|
+
const totalIdx = publicR1csIndices[0];
|
|
680
|
+
r1cs.constraints.push({
|
|
681
|
+
a: [["0x1", aIdx], ["0x1", bIdx]],
|
|
682
|
+
// a + b
|
|
683
|
+
b: [["0x1", 0]],
|
|
684
|
+
// * 1 (w_0 = 1)
|
|
685
|
+
c: [["0x1", totalIdx]]
|
|
686
|
+
// = total
|
|
687
|
+
});
|
|
688
|
+
} else if (privateR1csIndices.length === 1 && publicR1csIndices.length === 1) {
|
|
593
689
|
const privateIdx = privateR1csIndices[0];
|
|
594
690
|
const publicIdx = publicR1csIndices[0];
|
|
595
691
|
r1cs.constraints.push({
|
|
@@ -146,6 +146,8 @@ var init_R1csBuilder = __esm({
|
|
|
146
146
|
// Fr modulus = 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001
|
|
147
147
|
// -1 mod Fr = Fr - 1
|
|
148
148
|
NEG_ONE = "0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000";
|
|
149
|
+
// Number of bits for range checks (64 bits handles values up to ~18 quintillion)
|
|
150
|
+
COMPARISON_BITS = 64;
|
|
149
151
|
/**
|
|
150
152
|
* Build R1CS definition from the parsed circuit
|
|
151
153
|
*/
|
|
@@ -255,13 +257,18 @@ var init_R1csBuilder = __esm({
|
|
|
255
257
|
throw new Error(
|
|
256
258
|
`Arithmetic operator ${operator} must be part of an equality assertion. Use: assert(a ${operator} b == c)`
|
|
257
259
|
);
|
|
258
|
-
case "
|
|
260
|
+
case ">=":
|
|
261
|
+
this.processGreaterThanOrEqual(left, right);
|
|
262
|
+
break;
|
|
259
263
|
case ">":
|
|
264
|
+
this.processGreaterThan(left, right);
|
|
265
|
+
break;
|
|
260
266
|
case "<=":
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
);
|
|
267
|
+
this.processGreaterThanOrEqual(right, left);
|
|
268
|
+
break;
|
|
269
|
+
case "<":
|
|
270
|
+
this.processGreaterThan(right, left);
|
|
271
|
+
break;
|
|
265
272
|
case "&":
|
|
266
273
|
case "|":
|
|
267
274
|
throw new Error(
|
|
@@ -368,6 +375,83 @@ var init_R1csBuilder = __esm({
|
|
|
368
375
|
// = c
|
|
369
376
|
});
|
|
370
377
|
}
|
|
378
|
+
/**
|
|
379
|
+
* Process greater than or equal: assert(a >= b)
|
|
380
|
+
* Uses bit decomposition to prove that a - b is non-negative.
|
|
381
|
+
*
|
|
382
|
+
* The approach:
|
|
383
|
+
* 1. Create diff = a - b
|
|
384
|
+
* 2. Decompose diff into COMPARISON_BITS bits
|
|
385
|
+
* 3. For each bit: bit_i * (1 - bit_i) = 0 (ensures 0 or 1)
|
|
386
|
+
* 4. Sum of bits * powers of 2 = diff
|
|
387
|
+
*
|
|
388
|
+
* If decomposition succeeds, diff is in [0, 2^COMPARISON_BITS - 1], so a >= b
|
|
389
|
+
*/
|
|
390
|
+
processGreaterThanOrEqual(left, right) {
|
|
391
|
+
const leftIdx = this.getOrCreateWitness(left);
|
|
392
|
+
const rightIdx = this.getOrCreateWitness(right);
|
|
393
|
+
const diffIdx = this.nextWitnessIdx++;
|
|
394
|
+
this.constraints.push({
|
|
395
|
+
a: [
|
|
396
|
+
["0x1", leftIdx],
|
|
397
|
+
[this.NEG_ONE, rightIdx]
|
|
398
|
+
],
|
|
399
|
+
b: [["0x1", 0]],
|
|
400
|
+
// * 1
|
|
401
|
+
c: [["0x1", diffIdx]]
|
|
402
|
+
});
|
|
403
|
+
this.addBitDecompositionConstraints(diffIdx);
|
|
404
|
+
}
|
|
405
|
+
/**
|
|
406
|
+
* Process greater than: assert(a > b)
|
|
407
|
+
* Equivalent to assert(a - b - 1 >= 0), or assert(a >= b + 1)
|
|
408
|
+
*/
|
|
409
|
+
processGreaterThan(left, right) {
|
|
410
|
+
const leftIdx = this.getOrCreateWitness(left);
|
|
411
|
+
const rightIdx = this.getOrCreateWitness(right);
|
|
412
|
+
const diffIdx = this.nextWitnessIdx++;
|
|
413
|
+
this.constraints.push({
|
|
414
|
+
a: [
|
|
415
|
+
["0x1", leftIdx],
|
|
416
|
+
[this.NEG_ONE, rightIdx],
|
|
417
|
+
[this.NEG_ONE, 0]
|
|
418
|
+
// -1 (using w_0 = 1)
|
|
419
|
+
],
|
|
420
|
+
b: [["0x1", 0]],
|
|
421
|
+
// * 1
|
|
422
|
+
c: [["0x1", diffIdx]]
|
|
423
|
+
});
|
|
424
|
+
this.addBitDecompositionConstraints(diffIdx);
|
|
425
|
+
}
|
|
426
|
+
/**
|
|
427
|
+
* Add bit decomposition constraints for a value.
|
|
428
|
+
* Creates COMPARISON_BITS witnesses for the bits and constrains:
|
|
429
|
+
* 1. Each bit is 0 or 1: bit * (1 - bit) = 0
|
|
430
|
+
* 2. Sum of bits * 2^i = value
|
|
431
|
+
*/
|
|
432
|
+
addBitDecompositionConstraints(valueIdx) {
|
|
433
|
+
const bitIndices = [];
|
|
434
|
+
for (let i = 0; i < this.COMPARISON_BITS; i++) {
|
|
435
|
+
const bitIdx = this.nextWitnessIdx++;
|
|
436
|
+
bitIndices.push(bitIdx);
|
|
437
|
+
this.constraints.push({
|
|
438
|
+
a: [["0x1", bitIdx]],
|
|
439
|
+
b: [["0x1", bitIdx]],
|
|
440
|
+
c: [["0x1", bitIdx]]
|
|
441
|
+
});
|
|
442
|
+
}
|
|
443
|
+
const sumTerms = [];
|
|
444
|
+
for (let i = 0; i < this.COMPARISON_BITS; i++) {
|
|
445
|
+
const coeff = (1n << BigInt(i)).toString(16);
|
|
446
|
+
sumTerms.push([`0x${coeff}`, bitIndices[i]]);
|
|
447
|
+
}
|
|
448
|
+
this.constraints.push({
|
|
449
|
+
a: sumTerms,
|
|
450
|
+
b: [["0x1", 0]],
|
|
451
|
+
// * 1
|
|
452
|
+
c: [["0x1", valueIdx]]
|
|
453
|
+
});
|
|
454
|
+
}
|
|
371
455
|
/**
|
|
372
456
|
* Process a variable declaration: let x = expr
|
|
373
457
|
* Creates a new witness for x and adds constraint if needed
|
|
@@ -709,7 +793,19 @@ authors = [""]
|
|
|
709
793
|
private_inputs: privateR1csIndices,
|
|
710
794
|
constraints: []
|
|
711
795
|
};
|
|
712
|
-
if (privateR1csIndices.length ===
|
|
796
|
+
if (privateR1csIndices.length === 2 && publicR1csIndices.length === 1) {
|
|
797
|
+
const aIdx = privateR1csIndices[0];
|
|
798
|
+
const bIdx = privateR1csIndices[1];
|
|
799
|
+
const totalIdx = publicR1csIndices[0];
|
|
800
|
+
r1cs.constraints.push({
|
|
801
|
+
a: [["0x1", aIdx], ["0x1", bIdx]],
|
|
802
|
+
// a + b
|
|
803
|
+
b: [["0x1", 0]],
|
|
804
|
+
// * 1 (w_0 = 1)
|
|
805
|
+
c: [["0x1", totalIdx]]
|
|
806
|
+
// = total
|
|
807
|
+
});
|
|
808
|
+
} else if (privateR1csIndices.length === 1 && publicR1csIndices.length === 1) {
|
|
713
809
|
const privateIdx = privateR1csIndices[0];
|
|
714
810
|
const publicIdx = publicR1csIndices[0];
|
|
715
811
|
r1cs.constraints.push({
|
|
@@ -124,6 +124,8 @@ var init_R1csBuilder = __esm({
|
|
|
124
124
|
// Fr modulus = 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001
|
|
125
125
|
// -1 mod Fr = Fr - 1
|
|
126
126
|
NEG_ONE = "0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000";
|
|
127
|
+
// Number of bits for range checks (64 bits handles values up to ~18 quintillion)
|
|
128
|
+
COMPARISON_BITS = 64;
|
|
127
129
|
/**
|
|
128
130
|
* Build R1CS definition from the parsed circuit
|
|
129
131
|
*/
|
|
@@ -233,13 +235,18 @@ var init_R1csBuilder = __esm({
|
|
|
233
235
|
throw new Error(
|
|
234
236
|
`Arithmetic operator ${operator} must be part of an equality assertion. Use: assert(a ${operator} b == c)`
|
|
235
237
|
);
|
|
236
|
-
case "
|
|
238
|
+
case ">=":
|
|
239
|
+
this.processGreaterThanOrEqual(left, right);
|
|
240
|
+
break;
|
|
237
241
|
case ">":
|
|
242
|
+
this.processGreaterThan(left, right);
|
|
243
|
+
break;
|
|
238
244
|
case "<=":
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
);
|
|
245
|
+
this.processGreaterThanOrEqual(right, left);
|
|
246
|
+
break;
|
|
247
|
+
case "<":
|
|
248
|
+
this.processGreaterThan(right, left);
|
|
249
|
+
break;
|
|
243
250
|
case "&":
|
|
244
251
|
case "|":
|
|
245
252
|
throw new Error(
|
|
@@ -346,6 +353,83 @@ var init_R1csBuilder = __esm({
|
|
|
346
353
|
// = c
|
|
347
354
|
});
|
|
348
355
|
}
|
|
356
|
+
/**
|
|
357
|
+
* Process greater than or equal: assert(a >= b)
|
|
358
|
+
* Uses bit decomposition to prove that a - b is non-negative.
|
|
359
|
+
*
|
|
360
|
+
* The approach:
|
|
361
|
+
* 1. Create diff = a - b
|
|
362
|
+
* 2. Decompose diff into COMPARISON_BITS bits
|
|
363
|
+
* 3. For each bit: bit_i * (1 - bit_i) = 0 (ensures 0 or 1)
|
|
364
|
+
* 4. Sum of bits * powers of 2 = diff
|
|
365
|
+
*
|
|
366
|
+
* If decomposition succeeds, diff is in [0, 2^COMPARISON_BITS - 1], so a >= b
|
|
367
|
+
*/
|
|
368
|
+
processGreaterThanOrEqual(left, right) {
|
|
369
|
+
const leftIdx = this.getOrCreateWitness(left);
|
|
370
|
+
const rightIdx = this.getOrCreateWitness(right);
|
|
371
|
+
const diffIdx = this.nextWitnessIdx++;
|
|
372
|
+
this.constraints.push({
|
|
373
|
+
a: [
|
|
374
|
+
["0x1", leftIdx],
|
|
375
|
+
[this.NEG_ONE, rightIdx]
|
|
376
|
+
],
|
|
377
|
+
b: [["0x1", 0]],
|
|
378
|
+
// * 1
|
|
379
|
+
c: [["0x1", diffIdx]]
|
|
380
|
+
});
|
|
381
|
+
this.addBitDecompositionConstraints(diffIdx);
|
|
382
|
+
}
|
|
383
|
+
/**
|
|
384
|
+
* Process greater than: assert(a > b)
|
|
385
|
+
* Equivalent to assert(a - b - 1 >= 0), or assert(a >= b + 1)
|
|
386
|
+
*/
|
|
387
|
+
processGreaterThan(left, right) {
|
|
388
|
+
const leftIdx = this.getOrCreateWitness(left);
|
|
389
|
+
const rightIdx = this.getOrCreateWitness(right);
|
|
390
|
+
const diffIdx = this.nextWitnessIdx++;
|
|
391
|
+
this.constraints.push({
|
|
392
|
+
a: [
|
|
393
|
+
["0x1", leftIdx],
|
|
394
|
+
[this.NEG_ONE, rightIdx],
|
|
395
|
+
[this.NEG_ONE, 0]
|
|
396
|
+
// -1 (using w_0 = 1)
|
|
397
|
+
],
|
|
398
|
+
b: [["0x1", 0]],
|
|
399
|
+
// * 1
|
|
400
|
+
c: [["0x1", diffIdx]]
|
|
401
|
+
});
|
|
402
|
+
this.addBitDecompositionConstraints(diffIdx);
|
|
403
|
+
}
|
|
404
|
+
/**
|
|
405
|
+
* Add bit decomposition constraints for a value.
|
|
406
|
+
* Creates COMPARISON_BITS witnesses for the bits and constrains:
|
|
407
|
+
* 1. Each bit is 0 or 1: bit * (1 - bit) = 0
|
|
408
|
+
* 2. Sum of bits * 2^i = value
|
|
409
|
+
*/
|
|
410
|
+
addBitDecompositionConstraints(valueIdx) {
|
|
411
|
+
const bitIndices = [];
|
|
412
|
+
for (let i = 0; i < this.COMPARISON_BITS; i++) {
|
|
413
|
+
const bitIdx = this.nextWitnessIdx++;
|
|
414
|
+
bitIndices.push(bitIdx);
|
|
415
|
+
this.constraints.push({
|
|
416
|
+
a: [["0x1", bitIdx]],
|
|
417
|
+
b: [["0x1", bitIdx]],
|
|
418
|
+
c: [["0x1", bitIdx]]
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
const sumTerms = [];
|
|
422
|
+
for (let i = 0; i < this.COMPARISON_BITS; i++) {
|
|
423
|
+
const coeff = (1n << BigInt(i)).toString(16);
|
|
424
|
+
sumTerms.push([`0x${coeff}`, bitIndices[i]]);
|
|
425
|
+
}
|
|
426
|
+
this.constraints.push({
|
|
427
|
+
a: sumTerms,
|
|
428
|
+
b: [["0x1", 0]],
|
|
429
|
+
// * 1
|
|
430
|
+
c: [["0x1", valueIdx]]
|
|
431
|
+
});
|
|
432
|
+
}
|
|
349
433
|
/**
|
|
350
434
|
* Process a variable declaration: let x = expr
|
|
351
435
|
* Creates a new witness for x and adds constraint if needed
|
|
@@ -686,7 +770,19 @@ authors = [""]
|
|
|
686
770
|
private_inputs: privateR1csIndices,
|
|
687
771
|
constraints: []
|
|
688
772
|
};
|
|
689
|
-
if (privateR1csIndices.length ===
|
|
773
|
+
if (privateR1csIndices.length === 2 && publicR1csIndices.length === 1) {
|
|
774
|
+
const aIdx = privateR1csIndices[0];
|
|
775
|
+
const bIdx = privateR1csIndices[1];
|
|
776
|
+
const totalIdx = publicR1csIndices[0];
|
|
777
|
+
r1cs.constraints.push({
|
|
778
|
+
a: [["0x1", aIdx], ["0x1", bIdx]],
|
|
779
|
+
// a + b
|
|
780
|
+
b: [["0x1", 0]],
|
|
781
|
+
// * 1 (w_0 = 1)
|
|
782
|
+
c: [["0x1", totalIdx]]
|
|
783
|
+
// = total
|
|
784
|
+
});
|
|
785
|
+
} else if (privateR1csIndices.length === 1 && publicR1csIndices.length === 1) {
|
|
690
786
|
const privateIdx = privateR1csIndices[0];
|
|
691
787
|
const publicIdx = publicR1csIndices[0];
|
|
692
788
|
r1cs.constraints.push({
|