mirror of
https://github.com/selfxyz/self.git
synced 2026-01-09 14:48:06 -05:00
update circuit imports to @zk-email
This commit is contained in:
@@ -1,561 +0,0 @@
|
||||
pragma circom 2.1.5;
|
||||
|
||||
include "../../node_modules/circomlib/circuits/comparators.circom";
|
||||
include "../../node_modules/circomlib/circuits/bitify.circom";
|
||||
include "../../node_modules/circomlib/circuits/gates.circom";
|
||||
|
||||
include "./bigint_func.circom";
|
||||
|
||||
// addition mod 2**n with carry bit
|
||||
template ModSum(n) {
|
||||
assert(n <= 252);
|
||||
signal input a;
|
||||
signal input b;
|
||||
signal output sum;
|
||||
signal output carry;
|
||||
|
||||
component n2b = Num2Bits(n + 1);
|
||||
n2b.in <== a + b;
|
||||
carry <== n2b.out[n];
|
||||
sum <== a + b - carry * (1 << n);
|
||||
}
|
||||
|
||||
// a - b
|
||||
template ModSub(n) {
|
||||
assert(n <= 252);
|
||||
signal input a;
|
||||
signal input b;
|
||||
signal output out;
|
||||
signal output borrow;
|
||||
component lt = LessThan(n);
|
||||
lt.in[0] <== a;
|
||||
lt.in[1] <== b;
|
||||
borrow <== lt.out;
|
||||
out <== borrow * (1 << n) + a - b;
|
||||
}
|
||||
|
||||
// a - b - c
|
||||
// assume a - b - c + 2**n >= 0
|
||||
template ModSubThree(n) {
|
||||
assert(n + 2 <= 253);
|
||||
signal input a;
|
||||
signal input b;
|
||||
signal input c;
|
||||
assert(a - b - c + (1 << n) >= 0);
|
||||
signal output out;
|
||||
signal output borrow;
|
||||
signal b_plus_c;
|
||||
b_plus_c <== b + c;
|
||||
component lt = LessThan(n + 1);
|
||||
lt.in[0] <== a;
|
||||
lt.in[1] <== b_plus_c;
|
||||
borrow <== lt.out;
|
||||
out <== borrow * (1 << n) + a - b_plus_c;
|
||||
}
|
||||
|
||||
template ModSumThree(n) {
|
||||
assert(n + 2 <= 253);
|
||||
signal input a;
|
||||
signal input b;
|
||||
signal input c;
|
||||
signal output sum;
|
||||
signal output carry;
|
||||
|
||||
component n2b = Num2Bits(n + 2);
|
||||
n2b.in <== a + b + c;
|
||||
carry <== n2b.out[n] + 2 * n2b.out[n + 1];
|
||||
sum <== a + b + c - carry * (1 << n);
|
||||
}
|
||||
|
||||
template ModSumFour(n) {
|
||||
assert(n + 2 <= 253);
|
||||
signal input a;
|
||||
signal input b;
|
||||
signal input c;
|
||||
signal input d;
|
||||
signal output sum;
|
||||
signal output carry;
|
||||
|
||||
component n2b = Num2Bits(n + 2);
|
||||
n2b.in <== a + b + c + d;
|
||||
carry <== n2b.out[n] + 2 * n2b.out[n + 1];
|
||||
sum <== a + b + c + d - carry * (1 << n);
|
||||
}
|
||||
|
||||
// product mod 2**n with carry
|
||||
template ModProd(n) {
|
||||
assert(n <= 126);
|
||||
signal input a;
|
||||
signal input b;
|
||||
signal output prod;
|
||||
signal output carry;
|
||||
|
||||
component n2b = Num2Bits(2 * n);
|
||||
n2b.in <== a * b;
|
||||
|
||||
component b2n1 = Bits2Num(n);
|
||||
component b2n2 = Bits2Num(n);
|
||||
var i;
|
||||
for (i = 0; i < n; i++) {
|
||||
b2n1.in[i] <== n2b.out[i];
|
||||
b2n2.in[i] <== n2b.out[i + n];
|
||||
}
|
||||
prod <== b2n1.out;
|
||||
carry <== b2n2.out;
|
||||
}
|
||||
|
||||
// split a n + m bit input into two outputs
|
||||
template Split(n, m) {
|
||||
assert(n <= 126);
|
||||
signal input in;
|
||||
signal output small;
|
||||
signal output big;
|
||||
|
||||
small <-- in % (1 << n);
|
||||
big <-- in \ (1 << n);
|
||||
|
||||
component n2b_small = Num2Bits(n);
|
||||
n2b_small.in <== small;
|
||||
component n2b_big = Num2Bits(m);
|
||||
n2b_big.in <== big;
|
||||
|
||||
in === small + big * (1 << n);
|
||||
}
|
||||
|
||||
// split a n + m + k bit input into three outputs
|
||||
template SplitThree(n, m, k) {
|
||||
assert(n <= 126);
|
||||
signal input in;
|
||||
signal output small;
|
||||
signal output medium;
|
||||
signal output big;
|
||||
|
||||
small <-- in % (1 << n);
|
||||
medium <-- (in \ (1 << n)) % (1 << m);
|
||||
big <-- in \ (1 << n + m);
|
||||
|
||||
component n2b_small = Num2Bits(n);
|
||||
n2b_small.in <== small;
|
||||
component n2b_medium = Num2Bits(m);
|
||||
n2b_medium.in <== medium;
|
||||
component n2b_big = Num2Bits(k);
|
||||
n2b_big.in <== big;
|
||||
|
||||
in === small + medium * (1 << n) + big * (1 << n + m);
|
||||
}
|
||||
|
||||
// a[i], b[i] in 0... 2**n-1
|
||||
// represent a = a[0] + a[1] * 2**n + .. + a[k - 1] * 2**(n * k)
|
||||
template BigAdd(n, k) {
|
||||
assert(n <= 252);
|
||||
signal input a[k];
|
||||
signal input b[k];
|
||||
signal output out[k + 1];
|
||||
|
||||
component unit0 = ModSum(n);
|
||||
unit0.a <== a[0];
|
||||
unit0.b <== b[0];
|
||||
out[0] <== unit0.sum;
|
||||
|
||||
component unit[k - 1];
|
||||
for (var i = 1; i < k; i++) {
|
||||
unit[i - 1] = ModSumThree(n);
|
||||
unit[i - 1].a <== a[i];
|
||||
unit[i - 1].b <== b[i];
|
||||
if (i == 1) {
|
||||
unit[i - 1].c <== unit0.carry;
|
||||
} else {
|
||||
unit[i - 1].c <== unit[i - 2].carry;
|
||||
}
|
||||
out[i] <== unit[i - 1].sum;
|
||||
}
|
||||
out[k] <== unit[k - 2].carry;
|
||||
}
|
||||
|
||||
// a and b have n-bit registers
|
||||
// a has ka registers, each with NONNEGATIVE ma-bit values (ma can be > n)
|
||||
// b has kb registers, each with NONNEGATIVE mb-bit values (mb can be > n)
|
||||
// out has ka + kb - 1 registers, each with (ma + mb + ceil(log(max(ka, kb))))-bit values
|
||||
template BigMultNoCarry(n, ma, mb, ka, kb) {
|
||||
assert(ma + mb <= 253);
|
||||
signal input a[ka];
|
||||
signal input b[kb];
|
||||
signal output out[ka + kb - 1];
|
||||
|
||||
var prod_val[ka + kb - 1];
|
||||
for (var i = 0; i < ka + kb - 1; i++) {
|
||||
prod_val[i] = 0;
|
||||
}
|
||||
for (var i = 0; i < ka; i++) {
|
||||
for (var j = 0; j < kb; j++) {
|
||||
prod_val[i + j] += a[i] * b[j];
|
||||
}
|
||||
}
|
||||
for (var i = 0; i < ka + kb - 1; i++) {
|
||||
out[i] <-- prod_val[i];
|
||||
}
|
||||
|
||||
var a_poly[ka + kb - 1];
|
||||
var b_poly[ka + kb - 1];
|
||||
var out_poly[ka + kb - 1];
|
||||
for (var i = 0; i < ka + kb - 1; i++) {
|
||||
out_poly[i] = 0;
|
||||
a_poly[i] = 0;
|
||||
b_poly[i] = 0;
|
||||
for (var j = 0; j < ka + kb - 1; j++) {
|
||||
out_poly[i] = out_poly[i] + out[j] * (i ** j);
|
||||
}
|
||||
for (var j = 0; j < ka; j++) {
|
||||
a_poly[i] = a_poly[i] + a[j] * (i ** j);
|
||||
}
|
||||
for (var j = 0; j < kb; j++) {
|
||||
b_poly[i] = b_poly[i] + b[j] * (i ** j);
|
||||
}
|
||||
}
|
||||
for (var i = 0; i < ka + kb - 1; i++) {
|
||||
out_poly[i] === a_poly[i] * b_poly[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// in[i] contains longs
|
||||
// out[i] contains shorts
|
||||
template LongToShortNoEndCarry(n, k) {
|
||||
assert(n <= 126);
|
||||
signal input in[k];
|
||||
signal output out[k+1];
|
||||
|
||||
var split[k][3];
|
||||
for (var i = 0; i < k; i++) {
|
||||
split[i] = SplitThreeFn(in[i], n, n, n);
|
||||
}
|
||||
|
||||
var carry[k];
|
||||
carry[0] = 0;
|
||||
out[0] <-- split[0][0];
|
||||
if (k == 1) {
|
||||
out[1] <-- split[0][1];
|
||||
}
|
||||
if (k > 1) {
|
||||
var sumAndCarry[2] = SplitFn(split[0][1] + split[1][0], n, n);
|
||||
out[1] <-- sumAndCarry[0];
|
||||
carry[1] = sumAndCarry[1];
|
||||
}
|
||||
if (k == 2) {
|
||||
out[2] <-- split[1][1] + split[0][2] + carry[1];
|
||||
}
|
||||
if (k > 2) {
|
||||
for (var i = 2; i < k; i++) {
|
||||
var sumAndCarry[2] = SplitFn(split[i][0] + split[i-1][1] + split[i-2][2] + carry[i-1], n, n);
|
||||
out[i] <-- sumAndCarry[0];
|
||||
carry[i] = sumAndCarry[1];
|
||||
}
|
||||
out[k] <-- split[k-1][1] + split[k-2][2] + carry[k-1];
|
||||
}
|
||||
|
||||
component outRangeChecks[k+1];
|
||||
for (var i = 0; i < k+1; i++) {
|
||||
outRangeChecks[i] = Num2Bits(n);
|
||||
outRangeChecks[i].in <== out[i];
|
||||
}
|
||||
|
||||
signal runningCarry[k];
|
||||
component runningCarryRangeChecks[k];
|
||||
runningCarry[0] <-- (in[0] - out[0]) / (1 << n);
|
||||
runningCarryRangeChecks[0] = Num2Bits(n + log_ceil(k));
|
||||
runningCarryRangeChecks[0].in <== runningCarry[0];
|
||||
runningCarry[0] * (1 << n) === in[0] - out[0];
|
||||
for (var i = 1; i < k; i++) {
|
||||
runningCarry[i] <-- (in[i] - out[i] + runningCarry[i-1]) / (1 << n);
|
||||
runningCarryRangeChecks[i] = Num2Bits(n + log_ceil(k));
|
||||
runningCarryRangeChecks[i].in <== runningCarry[i];
|
||||
runningCarry[i] * (1 << n) === in[i] - out[i] + runningCarry[i-1];
|
||||
}
|
||||
runningCarry[k-1] === out[k];
|
||||
}
|
||||
|
||||
template BigMult(n, k) {
|
||||
signal input a[k];
|
||||
signal input b[k];
|
||||
signal output out[2 * k];
|
||||
|
||||
component mult = BigMultNoCarry(n, n, n, k, k);
|
||||
for (var i = 0; i < k; i++) {
|
||||
mult.a[i] <== a[i];
|
||||
mult.b[i] <== b[i];
|
||||
}
|
||||
|
||||
// no carry is possible in the highest order register
|
||||
component longshort = LongToShortNoEndCarry(n, 2 * k - 1);
|
||||
for (var i = 0; i < 2 * k - 1; i++) {
|
||||
longshort.in[i] <== mult.out[i];
|
||||
}
|
||||
for (var i = 0; i < 2 * k; i++) {
|
||||
out[i] <== longshort.out[i];
|
||||
}
|
||||
}
|
||||
|
||||
template BigLessThan(n, k){
|
||||
signal input a[k];
|
||||
signal input b[k];
|
||||
signal output out;
|
||||
|
||||
component lt[k];
|
||||
component eq[k];
|
||||
for (var i = 0; i < k; i++) {
|
||||
lt[i] = LessThan(n);
|
||||
lt[i].in[0] <== a[i];
|
||||
lt[i].in[1] <== b[i];
|
||||
eq[i] = IsEqual();
|
||||
eq[i].in[0] <== a[i];
|
||||
eq[i].in[1] <== b[i];
|
||||
}
|
||||
|
||||
// ors[i] holds (lt[k - 1] || (eq[k - 1] && lt[k - 2]) .. || (eq[k - 1] && .. && lt[i]))
|
||||
// ands[i] holds (eq[k - 1] && .. && lt[i])
|
||||
// eq_ands[i] holds (eq[k - 1] && .. && eq[i])
|
||||
component ors[k - 1];
|
||||
component ands[k - 1];
|
||||
component eq_ands[k - 1];
|
||||
for (var i = k - 2; i >= 0; i--) {
|
||||
ands[i] = AND();
|
||||
eq_ands[i] = AND();
|
||||
ors[i] = OR();
|
||||
|
||||
if (i == k - 2) {
|
||||
ands[i].a <== eq[k - 1].out;
|
||||
ands[i].b <== lt[k - 2].out;
|
||||
eq_ands[i].a <== eq[k - 1].out;
|
||||
eq_ands[i].b <== eq[k - 2].out;
|
||||
ors[i].a <== lt[k - 1].out;
|
||||
ors[i].b <== ands[i].out;
|
||||
} else {
|
||||
ands[i].a <== eq_ands[i + 1].out;
|
||||
ands[i].b <== lt[i].out;
|
||||
eq_ands[i].a <== eq_ands[i + 1].out;
|
||||
eq_ands[i].b <== eq[i].out;
|
||||
ors[i].a <== ors[i + 1].out;
|
||||
ors[i].b <== ands[i].out;
|
||||
}
|
||||
}
|
||||
out <== ors[0].out;
|
||||
}
|
||||
|
||||
template BigIsEqual(k){
|
||||
signal input in[2][k];
|
||||
signal output out;
|
||||
component isEqual[k+1];
|
||||
var sum = 0;
|
||||
for(var i = 0; i < k; i++){
|
||||
isEqual[i] = IsEqual();
|
||||
isEqual[i].in[0] <== in[0][i];
|
||||
isEqual[i].in[1] <== in[1][i];
|
||||
sum = sum + isEqual[i].out;
|
||||
}
|
||||
|
||||
isEqual[k] = IsEqual();
|
||||
isEqual[k].in[0] <== sum;
|
||||
isEqual[k].in[1] <== k;
|
||||
out <== isEqual[k].out;
|
||||
}
|
||||
|
||||
// leading register of b should be non-zero
|
||||
template BigMod(n, k) {
|
||||
assert(n <= 126);
|
||||
signal input a[2 * k];
|
||||
signal input b[k];
|
||||
|
||||
signal output div[k + 1];
|
||||
signal output mod[k];
|
||||
|
||||
var longdiv[2][100] = long_div(n, k, k, a, b);
|
||||
for (var i = 0; i < k; i++) {
|
||||
div[i] <-- longdiv[0][i];
|
||||
mod[i] <-- longdiv[1][i];
|
||||
}
|
||||
div[k] <-- longdiv[0][k];
|
||||
component range_checks[k + 1];
|
||||
for (var i = 0; i <= k; i++) {
|
||||
range_checks[i] = Num2Bits(n);
|
||||
range_checks[i].in <== div[i];
|
||||
}
|
||||
|
||||
component mul = BigMult(n, k + 1);
|
||||
for (var i = 0; i < k; i++) {
|
||||
mul.a[i] <== div[i];
|
||||
mul.b[i] <== b[i];
|
||||
}
|
||||
mul.a[k] <== div[k];
|
||||
mul.b[k] <== 0;
|
||||
|
||||
component add = BigAdd(n, 2 * k + 2);
|
||||
for (var i = 0; i < 2 * k; i++) {
|
||||
add.a[i] <== mul.out[i];
|
||||
if (i < k) {
|
||||
add.b[i] <== mod[i];
|
||||
} else {
|
||||
add.b[i] <== 0;
|
||||
}
|
||||
}
|
||||
add.a[2 * k] <== mul.out[2 * k];
|
||||
add.a[2 * k + 1] <== mul.out[2 * k + 1];
|
||||
add.b[2 * k] <== 0;
|
||||
add.b[2 * k + 1] <== 0;
|
||||
|
||||
for (var i = 0; i < 2 * k; i++) {
|
||||
add.out[i] === a[i];
|
||||
}
|
||||
add.out[2 * k] === 0;
|
||||
add.out[2 * k + 1] === 0;
|
||||
|
||||
component lt = BigLessThan(n, k);
|
||||
for (var i = 0; i < k; i++) {
|
||||
lt.a[i] <== mod[i];
|
||||
lt.b[i] <== b[i];
|
||||
}
|
||||
lt.out === 1;
|
||||
}
|
||||
|
||||
// a[i], b[i] in 0... 2**n-1
|
||||
// represent a = a[0] + a[1] * 2**n + .. + a[k - 1] * 2**(n * k)
|
||||
// assume a >= b
|
||||
template BigSub(n, k) {
|
||||
assert(n <= 252);
|
||||
signal input a[k];
|
||||
signal input b[k];
|
||||
signal output out[k];
|
||||
signal output underflow;
|
||||
|
||||
component unit0 = ModSub(n);
|
||||
unit0.a <== a[0];
|
||||
unit0.b <== b[0];
|
||||
out[0] <== unit0.out;
|
||||
|
||||
component unit[k - 1];
|
||||
for (var i = 1; i < k; i++) {
|
||||
unit[i - 1] = ModSubThree(n);
|
||||
unit[i - 1].a <== a[i];
|
||||
unit[i - 1].b <== b[i];
|
||||
if (i == 1) {
|
||||
unit[i - 1].c <== unit0.borrow;
|
||||
} else {
|
||||
unit[i - 1].c <== unit[i - 2].borrow;
|
||||
}
|
||||
out[i] <== unit[i - 1].out;
|
||||
}
|
||||
underflow <== unit[k - 2].borrow;
|
||||
}
|
||||
|
||||
// calculates (a - b) % p, where a, b < p
|
||||
// note: does not assume a >= b
|
||||
template BigSubModP(n, k){
|
||||
assert(n <= 252);
|
||||
signal input a[k];
|
||||
signal input b[k];
|
||||
signal input p[k];
|
||||
signal output out[k];
|
||||
component sub = BigSub(n, k);
|
||||
for (var i = 0; i < k; i++){
|
||||
sub.a[i] <== a[i];
|
||||
sub.b[i] <== b[i];
|
||||
}
|
||||
signal flag;
|
||||
flag <== sub.underflow;
|
||||
component add = BigAdd(n, k);
|
||||
for (var i = 0; i < k; i++){
|
||||
add.a[i] <== sub.out[i];
|
||||
add.b[i] <== flag * p[i];
|
||||
}
|
||||
for (var i = 0; i < k; i++){
|
||||
out[i] <== add.out[i];
|
||||
}
|
||||
}
|
||||
|
||||
template BigMultModP(n, k) {
|
||||
assert(n <= 252);
|
||||
signal input a[k];
|
||||
signal input b[k];
|
||||
signal input p[k];
|
||||
signal output out[k];
|
||||
|
||||
component big_mult = BigMult(n, k);
|
||||
for (var i = 0; i < k; i++) {
|
||||
big_mult.a[i] <== a[i];
|
||||
big_mult.b[i] <== b[i];
|
||||
}
|
||||
component big_mod = BigMod(n, k);
|
||||
for (var i = 0; i < 2 * k; i++) {
|
||||
big_mod.a[i] <== big_mult.out[i];
|
||||
}
|
||||
for (var i = 0; i < k; i++) {
|
||||
big_mod.b[i] <== p[i];
|
||||
}
|
||||
for (var i = 0; i < k; i++) {
|
||||
out[i] <== big_mod.mod[i];
|
||||
}
|
||||
}
|
||||
|
||||
template BigModInv(n, k) {
|
||||
assert(n <= 252);
|
||||
signal input in[k];
|
||||
signal input p[k];
|
||||
signal output out[k];
|
||||
|
||||
// length k
|
||||
var inv[100] = mod_inv(n, k, in, p);
|
||||
for (var i = 0; i < k; i++) {
|
||||
out[i] <-- inv[i];
|
||||
}
|
||||
component range_checks[k];
|
||||
for (var i = 0; i < k; i++) {
|
||||
range_checks[i] = Num2Bits(n);
|
||||
range_checks[i].in <== out[i];
|
||||
}
|
||||
|
||||
component mult = BigMult(n, k);
|
||||
for (var i = 0; i < k; i++) {
|
||||
mult.a[i] <== in[i];
|
||||
mult.b[i] <== out[i];
|
||||
}
|
||||
component mod = BigMod(n, k);
|
||||
for (var i = 0; i < 2 * k; i++) {
|
||||
mod.a[i] <== mult.out[i];
|
||||
}
|
||||
for (var i = 0; i < k; i++) {
|
||||
mod.b[i] <== p[i];
|
||||
}
|
||||
mod.mod[0] === 1;
|
||||
for (var i = 1; i < k; i++) {
|
||||
mod.mod[i] === 0;
|
||||
}
|
||||
}
|
||||
|
||||
// in[i] contains values in the range -2^(m-1) to 2^(m-1)
|
||||
// constrain that in[] as a big integer is zero
|
||||
// each limbs is n bits
|
||||
template CheckCarryToZero(n, m, k) {
|
||||
assert(k >= 2);
|
||||
|
||||
var EPSILON = 3;
|
||||
|
||||
assert(m + EPSILON <= 253);
|
||||
|
||||
signal input in[k];
|
||||
|
||||
signal carry[k];
|
||||
component carryRangeChecks[k];
|
||||
for (var i = 0; i < k-1; i++){
|
||||
carryRangeChecks[i] = Num2Bits(m + EPSILON - n);
|
||||
if( i == 0 ){
|
||||
carry[i] <-- in[i] / (1<<n);
|
||||
in[i] === carry[i] * (1<<n);
|
||||
}
|
||||
else{
|
||||
carry[i] <-- (in[i]+carry[i-1]) / (1<<n);
|
||||
in[i] + carry[i-1] === carry[i] * (1<<n);
|
||||
}
|
||||
// checking carry is in the range of - 2^(m-n-1+eps), 2^(m+-n-1+eps)
|
||||
carryRangeChecks[i].in <== carry[i] + ( 1<< (m + EPSILON - n - 1));
|
||||
}
|
||||
in[k-1] + carry[k-2] === 0;
|
||||
}
|
||||
@@ -1,442 +0,0 @@
|
||||
pragma circom 2.1.5;
|
||||
|
||||
function isNegative(x) {
|
||||
// half babyjubjub field size
|
||||
return x > 10944121435919637611123202872628637544274182200208017171849102093287904247808 ? 1 : 0;
|
||||
}
|
||||
|
||||
function div_ceil(m, n) {
|
||||
var ret = 0;
|
||||
if (m % n == 0) {
|
||||
ret = m \ n;
|
||||
} else {
|
||||
ret = m \ n + 1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
function log_ceil(n) {
|
||||
var n_temp = n;
|
||||
for (var i = 0; i < 254; i++) {
|
||||
if (n_temp == 0) {
|
||||
return i;
|
||||
}
|
||||
n_temp = n_temp \ 2;
|
||||
}
|
||||
return 254;
|
||||
}
|
||||
|
||||
function SplitFn(in, n, m) {
|
||||
return [in % (1 << n), (in \ (1 << n)) % (1 << m)];
|
||||
}
|
||||
|
||||
function SplitThreeFn(in, n, m, k) {
|
||||
return [in % (1 << n), (in \ (1 << n)) % (1 << m), (in \ (1 << n + m)) % (1 << k)];
|
||||
}
|
||||
|
||||
// m bits per overflowed register (values are potentially negative)
|
||||
// n bits per properly-sized register
|
||||
// in has k registers
|
||||
// out has k + ceil(m/n) - 1 + 1 registers. highest-order potentially negative,
|
||||
// all others are positive
|
||||
// - 1 since the last register is included in the last ceil(m/n) array
|
||||
// + 1 since the carries from previous registers could push you over
|
||||
function getProperRepresentation(m, n, k, in) {
|
||||
var ceilMN = div_ceil(m, n);
|
||||
|
||||
var out[100]; // should be out[k + ceilMN]
|
||||
assert(k + ceilMN < 100);
|
||||
for (var i = 0; i < k; i++) {
|
||||
out[i] = in[i];
|
||||
}
|
||||
for (var i = k; i < 100; i++) {
|
||||
out[i] = 0;
|
||||
}
|
||||
assert(n <= m);
|
||||
for (var i = 0; i+1 < k + ceilMN; i++) {
|
||||
assert((1 << m) >= out[i] && out[i] >= -(1 << m));
|
||||
var shifted_val = out[i] + (1 << m);
|
||||
assert(0 <= shifted_val && shifted_val <= (1 << (m+1)));
|
||||
out[i] = shifted_val & ((1 << n) - 1);
|
||||
out[i+1] += (shifted_val >> n) - (1 << (m - n));
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
// Evaluate polynomial a at point x
|
||||
function poly_eval(len, a, x) {
|
||||
var v = 0;
|
||||
for (var i = 0; i < len; i++) {
|
||||
v += a[i] * (x ** i);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
// Interpolate a degree len-1 polynomial given its evaluations at 0..len-1
|
||||
function poly_interp(len, v) {
|
||||
assert(len <= 200);
|
||||
var out[200];
|
||||
for (var i = 0; i < len; i++) {
|
||||
out[i] = 0;
|
||||
}
|
||||
|
||||
// Product_{i=0..len-1} (x-i)
|
||||
var full_poly[201];
|
||||
full_poly[0] = 1;
|
||||
for (var i = 0; i < len; i++) {
|
||||
full_poly[i+1] = 0;
|
||||
for (var j = i; j >= 0; j--) {
|
||||
full_poly[j+1] += full_poly[j];
|
||||
full_poly[j] *= -i;
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < len; i++) {
|
||||
var cur_v = 1;
|
||||
for (var j = 0; j < len; j++) {
|
||||
if (i == j) {
|
||||
// do nothing
|
||||
} else {
|
||||
cur_v *= i-j;
|
||||
}
|
||||
}
|
||||
cur_v = v[i] / cur_v;
|
||||
|
||||
var cur_rem = full_poly[len];
|
||||
for (var j = len-1; j >= 0; j--) {
|
||||
out[j] += cur_v * cur_rem;
|
||||
cur_rem = full_poly[j] + i * cur_rem;
|
||||
}
|
||||
assert(cur_rem == 0);
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
// 1 if true, 0 if false
|
||||
function long_gt(n, k, a, b) {
|
||||
for (var i = k - 1; i >= 0; i--) {
|
||||
if (a[i] > b[i]) {
|
||||
return 1;
|
||||
}
|
||||
if (a[i] < b[i]) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// n bits per register
|
||||
// a has k registers
|
||||
// b has k registers
|
||||
// a >= b
|
||||
function long_sub(n, k, a, b) {
|
||||
var diff[100];
|
||||
var borrow[100];
|
||||
for (var i = 0; i < k; i++) {
|
||||
if (i == 0) {
|
||||
if (a[i] >= b[i]) {
|
||||
diff[i] = a[i] - b[i];
|
||||
borrow[i] = 0;
|
||||
} else {
|
||||
diff[i] = a[i] - b[i] + (1 << n);
|
||||
borrow[i] = 1;
|
||||
}
|
||||
} else {
|
||||
if (a[i] >= b[i] + borrow[i - 1]) {
|
||||
diff[i] = a[i] - b[i] - borrow[i - 1];
|
||||
borrow[i] = 0;
|
||||
} else {
|
||||
diff[i] = (1 << n) + a[i] - b[i] - borrow[i - 1];
|
||||
borrow[i] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return diff;
|
||||
}
|
||||
|
||||
// a is a n-bit scalar
|
||||
// b has k registers
|
||||
function long_scalar_mult(n, k, a, b) {
|
||||
var out[100];
|
||||
for (var i = 0; i < 100; i++) {
|
||||
out[i] = 0;
|
||||
}
|
||||
for (var i = 0; i < k; i++) {
|
||||
var temp = out[i] + (a * b[i]);
|
||||
out[i] = temp % (1 << n);
|
||||
out[i + 1] = out[i + 1] + temp \ (1 << n);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
// n bits per register
|
||||
// a has k + m registers
|
||||
// b has k registers
|
||||
// out[0] has length m + 1 -- quotient
|
||||
// out[1] has length k -- remainder
|
||||
// implements algorithm of https://people.eecs.berkeley.edu/~fateman/282/F%20Wright%20notes/week4.pdf
|
||||
function long_div(n, k, m, a, b){
|
||||
var out[2][100];
|
||||
m += k;
|
||||
while (b[k-1] == 0) {
|
||||
out[1][k] = 0;
|
||||
k--;
|
||||
assert(k > 0);
|
||||
}
|
||||
m -= k;
|
||||
|
||||
var remainder[200];
|
||||
for (var i = 0; i < m + k; i++) {
|
||||
remainder[i] = a[i];
|
||||
}
|
||||
|
||||
var mult[200];
|
||||
var dividend[200];
|
||||
for (var i = m; i >= 0; i--) {
|
||||
if (i == m) {
|
||||
dividend[k] = 0;
|
||||
for (var j = k - 1; j >= 0; j--) {
|
||||
dividend[j] = remainder[j + m];
|
||||
}
|
||||
} else {
|
||||
for (var j = k; j >= 0; j--) {
|
||||
dividend[j] = remainder[j + i];
|
||||
}
|
||||
}
|
||||
|
||||
out[0][i] = short_div(n, k, dividend, b);
|
||||
|
||||
var mult_shift[100] = long_scalar_mult(n, k, out[0][i], b);
|
||||
var subtrahend[200];
|
||||
for (var j = 0; j < m + k; j++) {
|
||||
subtrahend[j] = 0;
|
||||
}
|
||||
for (var j = 0; j <= k; j++) {
|
||||
if (i + j < m + k) {
|
||||
subtrahend[i + j] = mult_shift[j];
|
||||
}
|
||||
}
|
||||
remainder = long_sub(n, m + k, remainder, subtrahend);
|
||||
}
|
||||
for (var i = 0; i < k; i++) {
|
||||
out[1][i] = remainder[i];
|
||||
}
|
||||
out[1][k] = 0;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
// n bits per register
|
||||
// a has k + 1 registers
|
||||
// b has k registers
|
||||
// assumes leading digit of b is at least 2 ** (n - 1)
|
||||
// 0 <= a < (2**n) * b
|
||||
function short_div_norm(n, k, a, b) {
|
||||
var qhat = (a[k] * (1 << n) + a[k - 1]) \ b[k - 1];
|
||||
if (qhat > (1 << n) - 1) {
|
||||
qhat = (1 << n) - 1;
|
||||
}
|
||||
|
||||
var mult[100] = long_scalar_mult(n, k, qhat, b);
|
||||
if (long_gt(n, k + 1, mult, a) == 1) {
|
||||
mult = long_sub(n, k + 1, mult, b);
|
||||
if (long_gt(n, k + 1, mult, a) == 1) {
|
||||
return qhat - 2;
|
||||
} else {
|
||||
return qhat - 1;
|
||||
}
|
||||
} else {
|
||||
return qhat;
|
||||
}
|
||||
}
|
||||
|
||||
// n bits per register
|
||||
// a has k + 1 registers
|
||||
// b has k registers
|
||||
// assumes leading digit of b is non-zero
|
||||
// 0 <= a < (2**n) * b
|
||||
function short_div(n, k, a, b) {
|
||||
var scale = (1 << n) \ (1 + b[k - 1]);
|
||||
|
||||
// k + 2 registers now
|
||||
var norm_a[200] = long_scalar_mult(n, k + 1, scale, a);
|
||||
// k + 1 registers now
|
||||
var norm_b[200] = long_scalar_mult(n, k, scale, b);
|
||||
|
||||
var ret;
|
||||
if (norm_b[k] != 0) {
|
||||
ret = short_div_norm(n, k + 1, norm_a, norm_b);
|
||||
} else {
|
||||
ret = short_div_norm(n, k, norm_a, norm_b);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// n bits per register
|
||||
// a and b both have k registers
|
||||
// out[0] has length 2 * k
|
||||
// adapted from BigMulShortLong and LongToShortNoEndCarry2 witness computation
|
||||
function prod(n, k, a, b) {
|
||||
// first compute the intermediate values. taken from BigMulShortLong
|
||||
var prod_val[100]; // length is 2 * k - 1
|
||||
for (var i = 0; i < 2 * k - 1; i++) {
|
||||
prod_val[i] = 0;
|
||||
if (i < k) {
|
||||
for (var a_idx = 0; a_idx <= i; a_idx++) {
|
||||
prod_val[i] = prod_val[i] + a[a_idx] * b[i - a_idx];
|
||||
}
|
||||
} else {
|
||||
for (var a_idx = i - k + 1; a_idx < k; a_idx++) {
|
||||
prod_val[i] = prod_val[i] + a[a_idx] * b[i - a_idx];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// now do a bunch of carrying to make sure registers not overflowed. taken from LongToShortNoEndCarry2
|
||||
var out[100]; // length is 2 * k
|
||||
|
||||
var split[100][3]; // first dimension has length 2 * k - 1
|
||||
for (var i = 0; i < 2 * k - 1; i++) {
|
||||
split[i] = SplitThreeFn(prod_val[i], n, n, n);
|
||||
}
|
||||
|
||||
var carry[100]; // length is 2 * k - 1
|
||||
carry[0] = 0;
|
||||
out[0] = split[0][0];
|
||||
if (2 * k - 1 > 1) {
|
||||
var sumAndCarry[2] = SplitFn(split[0][1] + split[1][0], n, n);
|
||||
out[1] = sumAndCarry[0];
|
||||
carry[1] = sumAndCarry[1];
|
||||
}
|
||||
if (2 * k - 1 > 2) {
|
||||
for (var i = 2; i < 2 * k - 1; i++) {
|
||||
var sumAndCarry[2] = SplitFn(split[i][0] + split[i-1][1] + split[i-2][2] + carry[i-1], n, n);
|
||||
out[i] = sumAndCarry[0];
|
||||
carry[i] = sumAndCarry[1];
|
||||
}
|
||||
out[2 * k - 1] = split[2*k-2][1] + split[2*k-3][2] + carry[2*k-2];
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
// n bits per register
|
||||
// a has k registers
|
||||
// p has k registers
|
||||
// e has k registers
|
||||
// k * n <= 500
|
||||
// p is a prime
|
||||
// computes a^e mod p
|
||||
function mod_exp(n, k, a, p, e) {
|
||||
var eBits[500]; // length is k * n
|
||||
for (var i = 0; i < k; i++) {
|
||||
for (var j = 0; j < n; j++) {
|
||||
eBits[j + n * i] = (e[i] >> j) & 1;
|
||||
}
|
||||
}
|
||||
|
||||
var out[100]; // length is k
|
||||
for (var i = 0; i < 100; i++) {
|
||||
out[i] = 0;
|
||||
}
|
||||
out[0] = 1;
|
||||
|
||||
// repeated squaring
|
||||
for (var i = k * n - 1; i >= 0; i--) {
|
||||
// multiply by a if bit is 0
|
||||
if (eBits[i] == 1) {
|
||||
var temp[200]; // length 2 * k
|
||||
temp = prod(n, k, out, a);
|
||||
var temp2[2][100];
|
||||
temp2 = long_div(n, k, k, temp, p);
|
||||
out = temp2[1];
|
||||
}
|
||||
|
||||
// square, unless we're at the end
|
||||
if (i > 0) {
|
||||
var temp[200]; // length 2 * k
|
||||
temp = prod(n, k, out, out);
|
||||
var temp2[2][100];
|
||||
temp2 = long_div(n, k, k, temp, p);
|
||||
out = temp2[1];
|
||||
}
|
||||
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
// n bits per register
|
||||
// a has k registers
|
||||
// p has k registers
|
||||
// k * n <= 500
|
||||
// p is a prime
|
||||
// if a == 0 mod p, returns 0
|
||||
// else computes inv = a^(p-2) mod p
|
||||
function mod_inv(n, k, a, p) {
|
||||
var isZero = 1;
|
||||
for (var i = 0; i < k; i++) {
|
||||
if (a[i] != 0) {
|
||||
isZero = 0;
|
||||
}
|
||||
}
|
||||
if (isZero == 1) {
|
||||
var ret[100];
|
||||
for (var i = 0; i < k; i++) {
|
||||
ret[i] = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
var pCopy[100];
|
||||
for (var i = 0; i < 100; i++) {
|
||||
if (i < k) {
|
||||
pCopy[i] = p[i];
|
||||
} else {
|
||||
pCopy[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
var two[100];
|
||||
for (var i = 0; i < 100; i++) {
|
||||
two[i] = 0;
|
||||
}
|
||||
two[0] = 2;
|
||||
|
||||
var pMinusTwo[100];
|
||||
pMinusTwo = long_sub(n, k, pCopy, two); // length k
|
||||
var out[100];
|
||||
out = mod_exp(n, k, a, pCopy, pMinusTwo);
|
||||
return out;
|
||||
}
|
||||
|
||||
// a, b and out are all n bits k registers
|
||||
function long_sub_mod_p(n, k, a, b, p){
|
||||
var gt = long_gt(n, k, a, b);
|
||||
var tmp[100];
|
||||
if(gt){
|
||||
tmp = long_sub(n, k, a, b);
|
||||
}
|
||||
else{
|
||||
tmp = long_sub(n, k, b, a);
|
||||
}
|
||||
var out[2][100];
|
||||
for(var i = k;i < 2 * k; i++){
|
||||
tmp[i] = 0;
|
||||
}
|
||||
out = long_div(n, k, k, tmp, p);
|
||||
if(gt==0){
|
||||
tmp = long_sub(n, k, p, out[1]);
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
// a, b, p and out are all n bits k registers
|
||||
function prod_mod_p(n, k, a, b, p){
|
||||
var tmp[100];
|
||||
var result[2][100];
|
||||
tmp = prod(n, k, a, b);
|
||||
result = long_div(n, k, k, tmp, p);
|
||||
return result[1];
|
||||
}
|
||||
@@ -1,175 +0,0 @@
|
||||
pragma circom 2.1.2;
|
||||
include "./utils.circom";
|
||||
|
||||
// circuits in this folder copied from zk-email, credits to them
|
||||
|
||||
// A set of utils for shifting and packing signal arrays
|
||||
// Performs extraction of reveal signals and packed signals
|
||||
|
||||
// From https://github.com/iden3/circomlib/blob/master/circuits/multiplexer.circom
|
||||
function log2(a) {
|
||||
if (a == 0) {
|
||||
return 0;
|
||||
}
|
||||
var n = 1;
|
||||
var r = 1;
|
||||
while (n<a) {
|
||||
r++;
|
||||
n *= 2;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
// Pack size is # of chunks i.e. number of char signals that fit into a signal (default 7 but can be 30)
|
||||
template PackBytes(max_in_signals, max_out_signals, pack_size) {
|
||||
assert(max_out_signals == ((max_in_signals - 1) \ pack_size + 1)); // Packing constant is wrong
|
||||
|
||||
signal input in[max_in_signals];
|
||||
signal output out[max_out_signals];
|
||||
|
||||
component packer[max_out_signals];
|
||||
for (var i = 0; i < max_out_signals; i++) {
|
||||
packer[i] = Bytes2Packed(pack_size);
|
||||
for (var j = 0; j < pack_size; j++) {
|
||||
var reveal_idx = i * pack_size + j;
|
||||
if (reveal_idx < max_in_signals) {
|
||||
packer[i].in[j] <== in[i * pack_size + j];
|
||||
} else {
|
||||
packer[i].in[j] <== 0;
|
||||
}
|
||||
}
|
||||
out[i] <== packer[i].out;
|
||||
}
|
||||
}
|
||||
|
||||
// Shift the input left by variable size of bytes.
|
||||
// From https://demo.hedgedoc.org/s/Le0R3xUhB
|
||||
// Note that if len_bits < max_substr * C, C around 1, then
|
||||
// it's more efficient to use Sampriti's O(nk) solution instead
|
||||
template VarShiftLeft(in_array_len, out_array_len) {
|
||||
var len_bits = log2(in_array_len);
|
||||
assert(in_array_len <= (1 << len_bits));
|
||||
signal input in[in_array_len]; // x
|
||||
signal input shift; // k
|
||||
|
||||
signal output out[out_array_len]; // y
|
||||
|
||||
component n2b = Num2Bits(len_bits);
|
||||
n2b.in <== shift;
|
||||
|
||||
signal tmp[len_bits][in_array_len];
|
||||
for (var j = 0; j < len_bits; j++) {
|
||||
for (var i = 0; i < in_array_len; i++) {
|
||||
var offset = (i + (1 << j)) % in_array_len;
|
||||
// Shift left by 2^j indices if bit is 1
|
||||
if (j == 0) {
|
||||
tmp[j][i] <== n2b.out[j] * (in[offset] - in[i]) + in[i];
|
||||
} else {
|
||||
tmp[j][i] <== n2b.out[j] * (tmp[j-1][offset] - tmp[j-1][i]) + tmp[j-1][i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return last row
|
||||
// TODO: Assert the rest of the values are 0
|
||||
for (var i = 0; i < out_array_len; i++) {
|
||||
out[i] <== tmp[len_bits - 1][i];
|
||||
}
|
||||
}
|
||||
|
||||
// Shift the input left by variable size of bytes.
|
||||
// Its input and output are the same as those of VarShiftLeft.
|
||||
// However, it assumes the input is the masked bytes and checks that shift is the first index of the non-masked bytes.
|
||||
template VarShiftMaskedStr(in_array_len, out_array_len) {
|
||||
signal input in[in_array_len]; // x
|
||||
signal input shift; // k
|
||||
signal output out[out_array_len] <== VarShiftLeft(in_array_len, out_array_len)(in, shift);
|
||||
|
||||
signal is_target_idx[in_array_len];
|
||||
signal prev_byte[in_array_len];
|
||||
signal is_this_zero[in_array_len];
|
||||
signal is_prev_zero[in_array_len];
|
||||
for(var i = 0; i < in_array_len; i++) {
|
||||
is_target_idx[i] <== IsEqual()([i, shift]);
|
||||
is_this_zero[i] <== IsZero()(in[i]);
|
||||
is_target_idx[i] * is_this_zero[i] === 0;
|
||||
if(i == 0) {
|
||||
is_prev_zero[i] <== 1;
|
||||
} else {
|
||||
is_prev_zero[i] <== IsZero()(in[i-1]);
|
||||
}
|
||||
is_target_idx[i] * (1 - is_prev_zero[i]) === 0;
|
||||
}
|
||||
}
|
||||
|
||||
// From https://demo.hedgedoc.org/s/Le0R3xUhB -- unused
|
||||
template ClearSubarrayAfterEndIndex(n, nBits) {
|
||||
signal input in[n]; // x
|
||||
signal input end; // k
|
||||
|
||||
signal output out[n]; // y
|
||||
|
||||
component lt[n];
|
||||
for (var i = 0; i < n; i++) {
|
||||
lt[i] = LessThan(nBits);
|
||||
lt[i].in[0] <== i;
|
||||
lt[i].in[1] <== end;
|
||||
|
||||
// y[i] = (i < k) * x[i]
|
||||
out[i] <== lt[i].out * in[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Lengths here are in signals, even though the final output array is 1/7 the size of max_substr_len
|
||||
// TODO: Maybe a better architectural decision to avoid mistakes is to require both values and assert their equality
|
||||
template ShiftAndPack(in_array_len, max_substr_len, pack_size) {
|
||||
var max_substr_len_packed = ((max_substr_len - 1) \ pack_size + 1);
|
||||
|
||||
component shifter = VarShiftLeft(in_array_len, max_substr_len);
|
||||
component packer = PackBytes(max_substr_len, max_substr_len_packed, pack_size);
|
||||
|
||||
signal input in[in_array_len];
|
||||
signal input shift;
|
||||
signal output out[max_substr_len_packed];
|
||||
|
||||
for (var i = 0; i < in_array_len; i++) {
|
||||
shifter.in[i] <== in[i];
|
||||
}
|
||||
shifter.shift <== shift;
|
||||
|
||||
// Note that this technically doesn't constrain the rest øf the bits after the max_substr_len to be 0/unmatched/unrevealed
|
||||
// Because of the constraints on signed inputs, it seems this should be OK security wise
|
||||
// But still, TODO unconstrained assert to double check they are 0
|
||||
for (var i = 0; i < max_substr_len; i++) {
|
||||
packer.in[i] <== shifter.out[i];
|
||||
}
|
||||
for (var i = 0; i < max_substr_len_packed; i++) {
|
||||
out[i] <== packer.out[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Shift the input left by variable size of bytes and pack the shifted bytes into fields under pack_size.
|
||||
// Its input and output are the same as those of ShiftAndPack.
|
||||
// However, it assumes the input is the masked bytes and checks that shift is the first index of the non-masked bytes.
|
||||
template ShiftAndPackMaskedStr(in_array_len, max_substr_len, pack_size) {
|
||||
var max_substr_len_packed = ((max_substr_len - 1) \ pack_size + 1);
|
||||
|
||||
component shifter = VarShiftMaskedStr(in_array_len, max_substr_len);
|
||||
component packer = PackBytes(max_substr_len, max_substr_len_packed, pack_size);
|
||||
|
||||
signal input in[in_array_len];
|
||||
signal input shift;
|
||||
signal output out[max_substr_len_packed];
|
||||
|
||||
for (var i = 0; i < in_array_len; i++) {
|
||||
shifter.in[i] <== in[i];
|
||||
}
|
||||
shifter.shift <== shift;
|
||||
|
||||
for (var i = 0; i < max_substr_len; i++) {
|
||||
packer.in[i] <== shifter.out[i];
|
||||
}
|
||||
for (var i = 0; i < max_substr_len_packed; i++) {
|
||||
out[i] <== packer.out[i];
|
||||
}
|
||||
}
|
||||
@@ -1,145 +0,0 @@
|
||||
pragma circom 2.1.5;
|
||||
|
||||
include "../../node_modules/circomlib/circuits/bitify.circom";
|
||||
include "../../node_modules/circomlib/circuits/comparators.circom";
|
||||
include "../../node_modules/circomlib/circuits/sign.circom";
|
||||
|
||||
include "./bigint.circom";
|
||||
include "./bigint_func.circom";
|
||||
|
||||
// These functions operate over values in Z/Zp for some integer p (typically,
|
||||
// but not necessarily prime). Values are stored as standard bignums with k
|
||||
// chunks of n bits, but intermediate values often have "overflow" bits inside
|
||||
// various chunks.
|
||||
//
|
||||
// These Fp functions will always correctly generate witnesses mod p, but they
|
||||
// do not *check* that values are normalized to < p; they only check that
|
||||
// values are correct mod p. This is to save the comparison circuit.
|
||||
// They *will* always check for intended results mod p (soundness), but it may
|
||||
// not have a unique intermediate signal.
|
||||
//
|
||||
// Conversely, some templates may not be satisfiable if the input witnesses are
|
||||
// not < p. This does not break completeness, as honest provers will always
|
||||
// generate witnesses which are canonical (between 0 and p).
|
||||
|
||||
// a * b = r mod p
|
||||
// a * b - p * q - r for some q
|
||||
template FpMul(n, k) {
|
||||
assert(n + n + log_ceil(k) + 2 <= 252);
|
||||
signal input a[k];
|
||||
signal input b[k];
|
||||
signal input p[k];
|
||||
|
||||
signal output out[k];
|
||||
|
||||
signal v_ab[2*k-1];
|
||||
for (var x = 0; x < 2*k-1; x++) {
|
||||
var v_a = poly_eval(k, a, x);
|
||||
var v_b = poly_eval(k, b, x);
|
||||
v_ab[x] <== v_a * v_b;
|
||||
}
|
||||
|
||||
var ab[200] = poly_interp(2*k-1, v_ab);
|
||||
// ab_proper has length 2*k
|
||||
var ab_proper[200] = getProperRepresentation(n + n + log_ceil(k), n, 2*k-1, ab);
|
||||
|
||||
var long_div_out[2][100] = long_div(n, k, k, ab_proper, p);
|
||||
|
||||
// Since we're only computing a*b, we know that q < p will suffice, so we
|
||||
// know it fits into k chunks and can do size n range checks.
|
||||
signal q[k];
|
||||
component q_range_check[k];
|
||||
signal r[k];
|
||||
component r_range_check[k];
|
||||
for (var i = 0; i < k; i++) {
|
||||
q[i] <-- long_div_out[0][i];
|
||||
q_range_check[i] = Num2Bits(n);
|
||||
q_range_check[i].in <== q[i];
|
||||
|
||||
r[i] <-- long_div_out[1][i];
|
||||
r_range_check[i] = Num2Bits(n);
|
||||
r_range_check[i].in <== r[i];
|
||||
}
|
||||
|
||||
signal v_pq_r[2*k-1];
|
||||
for (var x = 0; x < 2*k-1; x++) {
|
||||
var v_p = poly_eval(k, p, x);
|
||||
var v_q = poly_eval(k, q, x);
|
||||
var v_r = poly_eval(k, r, x);
|
||||
v_pq_r[x] <== v_p * v_q + v_r;
|
||||
}
|
||||
|
||||
signal v_t[2*k-1];
|
||||
for (var x = 0; x < 2*k-1; x++) {
|
||||
v_t[x] <== v_ab[x] - v_pq_r[x];
|
||||
}
|
||||
|
||||
var t[200] = poly_interp(2*k-1, v_t);
|
||||
component tCheck = CheckCarryToZero(n, n + n + log_ceil(k) + 2, 2*k-1);
|
||||
for (var i = 0; i < 2*k-1; i++) {
|
||||
tCheck.in[i] <== t[i];
|
||||
}
|
||||
|
||||
for (var i = 0; i < k; i++) {
|
||||
out[i] <== r[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Lifted from https://sourcegraph.com/github.com/darkforest-eth/circuits/-/blob/range_proof/circuit.circom
|
||||
// NB: RangeProof is inclusive.
|
||||
// input: field element, whose abs is claimed to be less than max_abs_value
|
||||
// output: none
|
||||
// we also want something like 4 * (abs(in) + max_abs_value) < 2 ** bits
|
||||
// and bits << 256
|
||||
// NB: RangeProof is inclusive.
|
||||
// input: field element, whose abs is claimed to be <= than max_abs_value
|
||||
// output: none
|
||||
// also checks that both max and abs(in) are expressible in `bits` bits
|
||||
template RangeProof(bits) {
|
||||
signal input in;
|
||||
signal input max_abs_value;
|
||||
|
||||
/* check that both max and abs(in) are expressible in `bits` bits */
|
||||
component n2b1 = Num2Bits(bits+1);
|
||||
n2b1.in <== in + (1 << bits);
|
||||
component n2b2 = Num2Bits(bits);
|
||||
n2b2.in <== max_abs_value;
|
||||
|
||||
/* check that in + max is between 0 and 2*max */
|
||||
component lowerBound = LessThan(bits+1);
|
||||
component upperBound = LessThan(bits+1);
|
||||
|
||||
lowerBound.in[0] <== max_abs_value + in;
|
||||
lowerBound.in[1] <== 0;
|
||||
lowerBound.out === 0;
|
||||
|
||||
upperBound.in[0] <== 2 * max_abs_value;
|
||||
upperBound.in[1] <== max_abs_value + in;
|
||||
upperBound.out === 0;
|
||||
}
|
||||
|
||||
// input: n field elements, whose abs are claimed to be less than max_abs_value
|
||||
// output: none
|
||||
template MultiRangeProof(n, bits) {
|
||||
signal input in[n];
|
||||
signal input max_abs_value;
|
||||
component rangeProofs[n];
|
||||
|
||||
for (var i = 0; i < n; i++) {
|
||||
rangeProofs[i] = RangeProof(bits);
|
||||
rangeProofs[i].in <== in[i];
|
||||
rangeProofs[i].max_abs_value <== max_abs_value;
|
||||
}
|
||||
}
|
||||
|
||||
template IsNegative(){
|
||||
signal input in;
|
||||
signal output out;
|
||||
component n2b = Num2Bits(254);
|
||||
component sign = Sign();
|
||||
in ==> n2b.in;
|
||||
for (var i = 0; i<254; i++) {
|
||||
n2b.out[i] ==> sign.in[i];
|
||||
}
|
||||
sign.sign ==> out;
|
||||
}
|
||||
@@ -1,149 +0,0 @@
|
||||
pragma circom 2.1.5;
|
||||
|
||||
include "../../node_modules/circomlib/circuits/bitify.circom";
|
||||
include "../../node_modules/circomlib/circuits/comparators.circom";
|
||||
include "../../node_modules/circomlib/circuits/mimcsponge.circom";
|
||||
include "./fp.circom";
|
||||
|
||||
// returns ceil(log2(a+1))
|
||||
function log2_ceil(a) {
|
||||
var n = a+1;
|
||||
var r = 0;
|
||||
while (n>0) {
|
||||
r++;
|
||||
n \= 2;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
// returns ceil(log2(a+1))
|
||||
function count_packed(n, chunks) {
|
||||
return (n - 1) \ chunks + 1;
|
||||
}
|
||||
|
||||
// Lifted from MACI https://github.com/privacy-scaling-explorations/maci/blob/v1/circuits/circom/trees/incrementalQuinTree.circom#L29
|
||||
// Bits is ceil(log2 choices)
|
||||
template QuinSelector(choices, bits) {
|
||||
signal input in[choices];
|
||||
signal input index;
|
||||
signal output out;
|
||||
|
||||
// Ensure that index < choices
|
||||
component lessThan = LessThan(bits);
|
||||
lessThan.in[0] <== index;
|
||||
lessThan.in[1] <== choices;
|
||||
lessThan.out === 1;
|
||||
|
||||
component calcTotal = CalculateTotal(choices);
|
||||
component eqs[choices];
|
||||
|
||||
// For each item, check whether its index equals the input index.
|
||||
for (var i = 0; i < choices; i ++) {
|
||||
eqs[i] = IsEqual();
|
||||
eqs[i].in[0] <== i;
|
||||
eqs[i].in[1] <== index;
|
||||
|
||||
// eqs[i].out is 1 if the index matches. As such, at most one input to
|
||||
// calcTotal is not 0.
|
||||
calcTotal.nums[i] <== eqs[i].out * in[i];
|
||||
}
|
||||
|
||||
// Returns 0 + 0 + ... + item
|
||||
out <== calcTotal.sum;
|
||||
}
|
||||
|
||||
template CalculateTotal(n) {
|
||||
signal input nums[n];
|
||||
signal output sum;
|
||||
|
||||
signal sums[n];
|
||||
sums[0] <== nums[0];
|
||||
|
||||
for (var i=1; i < n; i++) {
|
||||
sums[i] <== sums[i - 1] + nums[i];
|
||||
}
|
||||
|
||||
sum <== sums[n - 1];
|
||||
}
|
||||
|
||||
// Written by us
|
||||
// n bytes per signal, n = 31 usually
|
||||
template Packed2Bytes(n){
|
||||
signal input in; // < 2 ^ (8 * 31)
|
||||
signal output out[n]; // each out is < 64
|
||||
// Rangecheck in and out?
|
||||
|
||||
// Constrain bits
|
||||
component nbytes = Num2Bits(8 * n);
|
||||
nbytes.in <== in;
|
||||
component bytes[n];
|
||||
|
||||
for (var k = 0; k < n; k++){
|
||||
// Witness gen out
|
||||
out[k] <-- (in >> (k * 8)) % 256;
|
||||
|
||||
// Constrain bits to match
|
||||
bytes[k] = Num2Bits(8);
|
||||
bytes[k].in <== out[k];
|
||||
for (var j = 0; j < 8; j++) {
|
||||
nbytes.out[k * 8 + j] === bytes[k].out[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// n bytes per signal, n = 31 usually (i.e. 31 8-bit values being packed into 248 bits)
|
||||
// when calling this, you must constrain each 'in' value yourself to be < 256
|
||||
// TODO: Rangecheck in and out?
|
||||
template Bytes2Packed(n){
|
||||
signal input in[n]; // each in value is < 256 (i.e. 2^8)
|
||||
signal pow2[n+1]; // [k] is 2^k
|
||||
signal in_prefix_sum[n+1]; // each [k] is in[0] + 2^8 in[1]... 2^{8k-8} in[k-1]. cont.
|
||||
// [0] is 0. [1] is in[0]. [n+1] is out.
|
||||
signal output out; // < 2 ^ (8 * 31)
|
||||
// Rangecheck in and out?
|
||||
|
||||
// Witness gen out
|
||||
in_prefix_sum[0] <-- 0;
|
||||
for (var k = 0; k < n; k++){
|
||||
in_prefix_sum[k+1] <-- in_prefix_sum[k] + in[k] * (2 ** (k * 8));
|
||||
}
|
||||
out <-- in_prefix_sum[n];
|
||||
|
||||
// Constrain out bits
|
||||
component nbytes = Num2Bits(8 * n);
|
||||
nbytes.in <== out; // I think this auto-rangechecks out to be < 8*n bits.
|
||||
component bytes[n];
|
||||
|
||||
for (var k = 0; k < n; k++){
|
||||
bytes[k] = Num2Bits(8);
|
||||
bytes[k].in <== in[k];
|
||||
for (var j = 0; j < 8; j++) {
|
||||
nbytes.out[k * 8 + j] === bytes[k].out[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// salt_is_message_id_from, custom_anon_from_hashed_salt = MakeAnonEmailSalt(max_email_from_len, max_message_id_len)(email_from, custom_message_id_from, shifted_message_id)
|
||||
template MakeAnonEmailSalt(email_len, blinder_len) {
|
||||
signal input email[email_len];
|
||||
signal input custom_message_id[blinder_len]; // previous message id, used to source past account
|
||||
signal input original_message_id[blinder_len]; // previous message id, used to source past account
|
||||
signal intermediate_is_message_id_from[blinder_len + 1];
|
||||
signal isEq[blinder_len];
|
||||
signal output blinder_matches;
|
||||
signal output anon_salt;
|
||||
|
||||
component hasher = MiMCSponge(email_len + blinder_len, 220, 1);
|
||||
hasher.k <== 123;
|
||||
for (var i = 0; i < email_len; i++) {
|
||||
hasher.ins[i] <== email[i];
|
||||
}
|
||||
intermediate_is_message_id_from[0] <== 1;
|
||||
for (var i = 0; i < blinder_len; i++) {
|
||||
hasher.ins[i + email_len] <== custom_message_id[i];
|
||||
isEq[i] <== IsEqual()([custom_message_id[i], original_message_id[i]]);
|
||||
intermediate_is_message_id_from[i + 1] <== isEq[i] * intermediate_is_message_id_from[i];
|
||||
}
|
||||
blinder_matches <== intermediate_is_message_id_from[blinder_len];
|
||||
anon_salt <== hasher.outs[0];
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
pragma circom 2.1.5;
|
||||
|
||||
include "./rsa/rsa.circom";
|
||||
include "@zk-email/circuits/helpers/rsa.circom";
|
||||
include "@zk-email/circuits/helpers/extract.circom";
|
||||
include "./sha256Bytes.circom";
|
||||
include "../node_modules/circomlib/circuits/sha256/sha256.circom";
|
||||
|
||||
template PassportVerifier(n, k) {
|
||||
signal input mrz[93]; // formatted mrz (5 + 88) chars
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
pragma circom 2.1.5;
|
||||
|
||||
include "../node_modules/circomlib/circuits/poseidon.circom";
|
||||
include "./helpers/extract.circom";
|
||||
include "circomlib/circuits/poseidon.circom";
|
||||
include "@zk-email/circuits/helpers/extract.circom";
|
||||
include "./passport_verifier.circom";
|
||||
|
||||
template ProofOfPassport(n, k) {
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 zk-email
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -1,156 +0,0 @@
|
||||
pragma circom 2.1.5;
|
||||
|
||||
include "../helpers/fp.circom";
|
||||
|
||||
// Computes base^65537 mod modulus
|
||||
// Does not necessarily reduce fully mod modulus (the answer could be
|
||||
// too big by a multiple of modulus)
|
||||
template FpPow65537Mod(n, k) {
|
||||
signal input base[k];
|
||||
// Exponent is hardcoded at 65537
|
||||
signal input modulus[k];
|
||||
signal output out[k];
|
||||
|
||||
component doublers[16];
|
||||
component adder = FpMul(n, k);
|
||||
for (var i = 0; i < 16; i++) {
|
||||
doublers[i] = FpMul(n, k);
|
||||
}
|
||||
|
||||
for (var j = 0; j < k; j++) {
|
||||
adder.p[j] <== modulus[j];
|
||||
for (var i = 0; i < 16; i++) {
|
||||
doublers[i].p[j] <== modulus[j];
|
||||
}
|
||||
}
|
||||
for (var j = 0; j < k; j++) {
|
||||
doublers[0].a[j] <== base[j];
|
||||
doublers[0].b[j] <== base[j];
|
||||
}
|
||||
for (var i = 0; i + 1 < 16; i++) {
|
||||
for (var j = 0; j < k; j++) {
|
||||
doublers[i + 1].a[j] <== doublers[i].out[j];
|
||||
doublers[i + 1].b[j] <== doublers[i].out[j];
|
||||
}
|
||||
}
|
||||
for (var j = 0; j < k; j++) {
|
||||
adder.a[j] <== base[j];
|
||||
adder.b[j] <== doublers[15].out[j];
|
||||
}
|
||||
for (var j = 0; j < k; j++) {
|
||||
out[j] <== adder.out[j];
|
||||
}
|
||||
}
|
||||
|
||||
template RSAPad(n, k) {
|
||||
signal input modulus[k];
|
||||
signal input base_message[k];
|
||||
signal output padded_message[k];
|
||||
|
||||
var base_len = 408;
|
||||
var msg_len = 256;
|
||||
|
||||
signal padded_message_bits[n*k];
|
||||
|
||||
component modulus_n2b[k];
|
||||
component base_message_n2b[k];
|
||||
signal modulus_bits[n*k];
|
||||
signal base_message_bits[n*k];
|
||||
for (var i = 0; i < k; i++) {
|
||||
base_message_n2b[i] = Num2Bits(n);
|
||||
base_message_n2b[i].in <== base_message[i];
|
||||
for (var j = 0; j < n; j++) {
|
||||
base_message_bits[i*n+j] <== base_message_n2b[i].out[j];
|
||||
}
|
||||
modulus_n2b[i] = Num2Bits(n);
|
||||
modulus_n2b[i].in <== modulus[i];
|
||||
for (var j = 0; j < n; j++) {
|
||||
modulus_bits[i*n+j] <== modulus_n2b[i].out[j];
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = msg_len; i < n*k; i++) {
|
||||
base_message_bits[i] === 0;
|
||||
}
|
||||
|
||||
for (var i = 0; i < msg_len; i++) {
|
||||
padded_message_bits[i] <== base_message_bits[i];
|
||||
}
|
||||
|
||||
for (var i = base_len; i < base_len + 8; i++) {
|
||||
padded_message_bits[i] <== 0;
|
||||
}
|
||||
|
||||
for (var i = msg_len; i < base_len; i++) {
|
||||
padded_message_bits[i] <== (0x3031300d060960864801650304020105000420 >> (i - msg_len)) & 1;
|
||||
}
|
||||
|
||||
component modulus_zero[(n*k + 7 - (base_len + 8))\8];
|
||||
{
|
||||
var modulus_prefix = 0;
|
||||
for (var i = n*k - 1; i >= base_len + 8; i--) {
|
||||
if (i+8 < n*k) {
|
||||
modulus_prefix += modulus_bits[i+8];
|
||||
if (i % 8 == 0) {
|
||||
var idx = (i - (base_len + 8)) / 8;
|
||||
modulus_zero[idx] = IsZero();
|
||||
modulus_zero[idx].in <== modulus_prefix;
|
||||
padded_message_bits[i] <== 1-modulus_zero[idx].out;
|
||||
} else {
|
||||
padded_message_bits[i] <== padded_message_bits[i+1];
|
||||
}
|
||||
} else {
|
||||
padded_message_bits[i] <== 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The RFC guarantees at least 8 octets of 0xff padding.
|
||||
assert(base_len + 8 + 65 <= n*k);
|
||||
for (var i = base_len + 8; i < base_len + 8 + 65; i++) {
|
||||
padded_message_bits[i] === 1;
|
||||
}
|
||||
|
||||
component padded_message_b2n[k];
|
||||
for (var i = 0; i < k; i++) {
|
||||
padded_message_b2n[i] = Bits2Num(n);
|
||||
for (var j = 0; j < n; j++) {
|
||||
padded_message_b2n[i].in[j] <== padded_message_bits[i*n+j];
|
||||
}
|
||||
padded_message[i] <== padded_message_b2n[i].out;
|
||||
}
|
||||
}
|
||||
|
||||
template RSAVerify65537(n, k) {
|
||||
signal input signature[k];
|
||||
signal input modulus[k];
|
||||
signal input base_message[k];
|
||||
|
||||
component padder = RSAPad(n, k);
|
||||
for (var i = 0; i < k; i++) {
|
||||
padder.modulus[i] <== modulus[i];
|
||||
padder.base_message[i] <== base_message[i];
|
||||
}
|
||||
|
||||
// Check that the signature is in proper form and reduced mod modulus.
|
||||
component signatureRangeCheck[k];
|
||||
component bigLessThan = BigLessThan(n, k);
|
||||
for (var i = 0; i < k; i++) {
|
||||
signatureRangeCheck[i] = Num2Bits(n);
|
||||
signatureRangeCheck[i].in <== signature[i];
|
||||
bigLessThan.a[i] <== signature[i];
|
||||
bigLessThan.b[i] <== modulus[i];
|
||||
}
|
||||
bigLessThan.out === 1;
|
||||
|
||||
component bigPow = FpPow65537Mod(n, k);
|
||||
for (var i = 0; i < k; i++) {
|
||||
bigPow.base[i] <== signature[i];
|
||||
bigPow.modulus[i] <== modulus[i];
|
||||
}
|
||||
// By construction of the padding, the padded message is necessarily
|
||||
// smaller than the modulus. Thus, we don't have to check that bigPow is fully reduced.
|
||||
for (var i = 0; i < k; i++) {
|
||||
bigPow.out[i] === padder.padded_message[i];
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,7 @@
|
||||
pragma circom 2.1.5;
|
||||
|
||||
include "../node_modules/circomlib/circuits/bitify.circom";
|
||||
include "../node_modules/circomlib/circuits/sha256/sha256.circom";
|
||||
include "../node_modules/circomlib/circuits/bitify.circom";
|
||||
include "circomlib/circuits/bitify.circom";
|
||||
include "circomlib/circuits/sha256/sha256.circom";
|
||||
|
||||
template Sha256Bytes(max_num_bytes) {
|
||||
signal input in_padded[max_num_bytes];
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
"@types/chai-as-promised": "^7.1.6",
|
||||
"@types/node": "^20.6.3",
|
||||
"@types/node-forge": "^1.3.5",
|
||||
"@zk-email/circuits": "^3.2.2",
|
||||
"chai-as-promised": "^7.1.1",
|
||||
"circomlib": "^2.0.5",
|
||||
"js-sha256": "^0.10.1",
|
||||
|
||||
@@ -20,7 +20,7 @@ fi
|
||||
cd ..
|
||||
|
||||
echo "compiling circuit"
|
||||
circom circuits/proof_of_passport.circom --r1cs --wasm --output build
|
||||
circom circuits/proof_of_passport.circom -l node_modules --r1cs --wasm --output build
|
||||
|
||||
mkdir -p ../app/ark-circom-passport/passport/
|
||||
cp build/proof_of_passport.r1cs ../app/ark-circom-passport/passport/
|
||||
|
||||
@@ -49,6 +49,21 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.6.3.tgz#5b763b321cd3b80f6b8dde7a37e1a77ff9358dd9"
|
||||
integrity sha512-HksnYH4Ljr4VQgEy2lTStbCKv/P590tmPe5HqOnv9Gprffgv5WXAY+Y5Gqniu0GGqeTCUdBnzC3QSrzPkBkAMA==
|
||||
|
||||
"@zk-email/circuits@^3.2.2":
|
||||
version "3.2.2"
|
||||
resolved "https://registry.yarnpkg.com/@zk-email/circuits/-/circuits-3.2.2.tgz#019d10e644ba1a3ad73bd8d73a66f53149c530dd"
|
||||
integrity sha512-3R2y64IeNq7cnfJabAlmQflhGlNAhcR4vq9n55fAIbgpYQ8P2d4k5Aa52HK8mqaVDCnNjLlAWMni557TUqQuGg==
|
||||
dependencies:
|
||||
"@zk-email/zk-regex-circom" "^1.1.1"
|
||||
|
||||
"@zk-email/zk-regex-circom@^1.1.1":
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@zk-email/zk-regex-circom/-/zk-regex-circom-1.2.1.tgz#ea1adc832e8d855c9568abc438567a524a0ac962"
|
||||
integrity sha512-+AoH5PdKZxatTWfwYWGkpuQ0xGaax6FwBHvdYXugkPDdgtJQYyxhItQtM79bo0djCmuwEK2X1rnYlFHBDClQeA==
|
||||
dependencies:
|
||||
commander "^11.0.0"
|
||||
snarkjs "^0.7.0"
|
||||
|
||||
ansi-colors@4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348"
|
||||
@@ -256,6 +271,11 @@ color-name@~1.1.4:
|
||||
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
|
||||
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
|
||||
|
||||
commander@^11.0.0:
|
||||
version "11.1.0"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-11.1.0.tgz#62fdce76006a68e5c1ab3314dc92e800eb83d906"
|
||||
integrity sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==
|
||||
|
||||
concat-map@0.0.1:
|
||||
version "0.0.1"
|
||||
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
||||
@@ -368,6 +388,15 @@ ffjavascript@0.2.60, ffjavascript@^0.2.48:
|
||||
wasmcurves "0.2.2"
|
||||
web-worker "^1.2.0"
|
||||
|
||||
ffjavascript@0.2.63:
|
||||
version "0.2.63"
|
||||
resolved "https://registry.yarnpkg.com/ffjavascript/-/ffjavascript-0.2.63.tgz#0c1216a1f123dc9181df69e144473704d2f115eb"
|
||||
integrity sha512-dBgdsfGks58b66JnUZeZpGxdMIDQ4QsD3VYlRJyFVrKQHb2kJy4R2gufx5oetrTxXPT+aEjg0dOvOLg1N0on4A==
|
||||
dependencies:
|
||||
wasmbuilder "0.0.16"
|
||||
wasmcurves "0.2.2"
|
||||
web-worker "1.2.0"
|
||||
|
||||
filelist@^1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/filelist/-/filelist-1.0.4.tgz#f78978a1e944775ff9e62e744424f215e58352b5"
|
||||
@@ -773,6 +802,22 @@ serialize-javascript@6.0.0:
|
||||
dependencies:
|
||||
randombytes "^2.1.0"
|
||||
|
||||
snarkjs@^0.7.0:
|
||||
version "0.7.3"
|
||||
resolved "https://registry.yarnpkg.com/snarkjs/-/snarkjs-0.7.3.tgz#7f703d05b810235255f2d0a70d8a9b8b3ea916e5"
|
||||
integrity sha512-cDLpWqdqEJSCQNc+cXYX1XTKdUZBtYEisuOsgmXf/HUsN5WmGN+FO7HfCS+cMQT1Nzbm1a9gAEpKH6KRtDtS1Q==
|
||||
dependencies:
|
||||
"@iden3/binfileutils" "0.0.11"
|
||||
bfj "^7.0.2"
|
||||
blake2b-wasm "^2.4.0"
|
||||
circom_runtime "0.1.24"
|
||||
ejs "^3.1.6"
|
||||
fastfile "0.0.20"
|
||||
ffjavascript "0.2.63"
|
||||
js-sha3 "^0.8.0"
|
||||
logplease "^1.2.15"
|
||||
r1csfile "0.0.47"
|
||||
|
||||
snarkjs@^0.7.1:
|
||||
version "0.7.1"
|
||||
resolved "https://registry.yarnpkg.com/snarkjs/-/snarkjs-0.7.1.tgz#c96ecaf4db8c2eb44d60b17ee02f37ed39c821bb"
|
||||
@@ -928,7 +973,7 @@ wasmcurves@0.2.2:
|
||||
dependencies:
|
||||
wasmbuilder "0.0.16"
|
||||
|
||||
web-worker@^1.2.0:
|
||||
web-worker@1.2.0, web-worker@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/web-worker/-/web-worker-1.2.0.tgz#5d85a04a7fbc1e7db58f66595d7a3ac7c9c180da"
|
||||
integrity sha512-PgF341avzqyx60neE9DD+XS26MMNMoUQRz9NOZwW32nPQrF6p77f1htcnjBSEV8BGMKZ16choqUG4hyI0Hx7mA==
|
||||
|
||||
Reference in New Issue
Block a user