-
Notifications
You must be signed in to change notification settings - Fork 74
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #195 from privacy-scaling-explorations/feat/maci-c…
…ircuits Add MACI template circuits
- Loading branch information
Showing
9 changed files
with
1,473 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
pragma circom 2.1.5; | ||
|
||
// circomlib imports | ||
include "./bitify.circom"; | ||
include "./escalarmulany.circom"; | ||
|
||
// ECDH Is a a template which allows to generate a shared secret | ||
// from a private key and a public key | ||
// on the baby jubjub curve | ||
// It is important that the private key is hashed and pruned first | ||
// which can be accomplished using the function | ||
// deriveScalar from @zk-kit/baby-jubjub | ||
template Ecdh() { | ||
// the private key must pass through deriveScalar first | ||
signal input privateKey; | ||
signal input publicKey[2]; | ||
|
||
signal output sharedKey[2]; | ||
|
||
// convert the private key to its bits representation | ||
var out[253]; | ||
out = Num2Bits(253)(privateKey); | ||
|
||
// multiply the public key by the private key | ||
var mulFix[2]; | ||
mulFix = EscalarMulAny(253)(out, publicKey); | ||
|
||
// we can then wire the output to the shared secret signal | ||
sharedKey <== mulFix; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,205 @@ | ||
pragma circom 2.1.5; | ||
|
||
include "./bitify.circom"; | ||
include "./comparators.circom"; | ||
include "./mux1.circom"; | ||
|
||
// Template to determine the most significant bit (MSB) of an input number. | ||
template MSB(n) { | ||
signal input in; | ||
signal output out; | ||
|
||
// Convert the number to its bit representation. | ||
var n2b[n]; | ||
n2b = Num2Bits(n)(in); | ||
|
||
// Assign the MSB to the output. | ||
out <== n2b[n-1]; | ||
} | ||
|
||
// Template for bit-shifting a dividend and partial remainder. | ||
template Shift(n) { | ||
// Dividend. | ||
signal input dividend; | ||
// Remainder. | ||
signal input remainder; | ||
|
||
// Shifted dividend. | ||
signal output outDividend; | ||
// Partial remainder (updated). | ||
signal output outRemainder; | ||
|
||
// Determine the MSB of the dividend. | ||
var lmsb; | ||
lmsb = MSB(n)(dividend); | ||
|
||
// Shift the dividend. | ||
outDividend <== dividend - lmsb * 2 ** (n - 1); | ||
|
||
// Update the partial remainder. | ||
outRemainder <== remainder * 2 + lmsb; | ||
} | ||
|
||
// Template for performing integer division. | ||
template IntegerDivision(n) { | ||
// Dividend. | ||
signal input a; | ||
// Divisor. | ||
signal input b; | ||
// Quotient. | ||
signal output c; | ||
|
||
// Ensure inputs are within the valid range. | ||
var lta; | ||
var ltb; | ||
|
||
lta = LessThan(252)([a, 2**n]); | ||
ltb = LessThan(252)([b, 2**n]); | ||
|
||
assert(lta == 1); | ||
assert(ltb == 1); | ||
|
||
// Ensure the divisor 'b' is not zero. | ||
var isz; | ||
|
||
isz = IsZero()(b); | ||
|
||
assert(isz == 0); | ||
|
||
// Prepare variables for division. | ||
var dividend = a; | ||
var remainder = 0; | ||
|
||
var bits[n]; | ||
|
||
// Loop to perform division through bit-shifting and subtraction. | ||
for (var i = n - 1; i >= 0; i--) { | ||
// Shift 'dividend' and 'rem' and determine if 'b' can be subtracted from the new 'rem'. | ||
var shiftedDividend; | ||
var shiftedRem; | ||
|
||
(shiftedDividend, shiftedRem) = Shift(i + 1)(dividend, remainder); | ||
|
||
// Determine if 'b' <= 'rem'. | ||
var canSubtract; | ||
|
||
canSubtract = LessEqThan(n)([b, shiftedRem]); | ||
|
||
// Select 1 if 'b' can be subtracted (i.e., 'b' <= 'rem'), else select 0. | ||
var subtractBit; | ||
|
||
subtractBit = Mux1()([0, 1], canSubtract); | ||
|
||
// Subtract 'b' from 'rem' if possible, and set the corresponding bit in 'bits'. | ||
bits[i] = subtractBit; | ||
|
||
remainder = shiftedRem - b * subtractBit; | ||
|
||
// Prepare 'dividend' for the next iteration. | ||
dividend = shiftedDividend; | ||
} | ||
|
||
// Convert the bit array representing the quotient into a number. | ||
c <== Bits2Num(n)(bits); | ||
} | ||
|
||
// Converts an integer to its floating-point representation by multiplying it with 10^W. | ||
template ToFloat(W) { | ||
// Assert W to ensure the result is within the range of 2^252. | ||
assert(W < 75); | ||
|
||
signal input in; | ||
|
||
signal output out; | ||
|
||
// Ensure the input multiplied by 10^W is less than 10^75 to prevent overflow. | ||
var lt; | ||
|
||
lt = LessEqThan(252)([in, 10 ** (75 - W)]); | ||
|
||
assert(lt == 1); | ||
|
||
// Convert the integer to floating-point by multiplying with 10^W. | ||
out <== in * (10**W); | ||
} | ||
|
||
// Performs division on floating-point numbers represented with W decimal digits. | ||
template DivisionFromFloat(W, n) { | ||
// Ensure W is within the valid range for floating-point representation. | ||
assert(W < 75); | ||
// Ensure n, the bit-width of inputs, is within a valid range. | ||
assert(n < 252); | ||
|
||
// Numerator. | ||
signal input a; | ||
// Denominator. | ||
signal input b; | ||
// Quotient. | ||
signal output c; | ||
|
||
// Ensure the numerator 'a' is within the range of valid floating-point numbers. | ||
var lt; | ||
|
||
lt = LessEqThan(252)([a, 10 ** (75 - W)]); | ||
|
||
assert(lt == 1); | ||
|
||
// Use IntegerDivision for division operation. | ||
c <== IntegerDivision(n)(a * (10 ** W), b); | ||
} | ||
|
||
// Performs division on integers by first converting them to floating-point representation. | ||
template DivisionFromNormal(W, n) { | ||
// Numerator. | ||
signal input a; | ||
// Denominator. | ||
signal input b; | ||
// Quotient. | ||
signal output c; | ||
|
||
// Convert input to float and perform division. | ||
c <== DivisionFromFloat(W, n)(ToFloat(W)(a), ToFloat(W)(b)); | ||
} | ||
|
||
// Performs multiplication on floating-point numbers and converts the result back to integer form. | ||
template MultiplicationFromFloat(W, n) { | ||
// Ensure W is within the valid range for floating-point representation. | ||
assert(W < 75); | ||
// Ensure n, the bit-width of inputs, is within a valid range. | ||
assert(n < 252); | ||
// Ensure scaling factor is within the range of 'n' bits. | ||
assert(10**W < 2**n); | ||
|
||
// Multiplicand. | ||
signal input a; | ||
// Multiplier. | ||
signal input b; | ||
// Product. | ||
signal output c; | ||
|
||
// Ensure both inputs 'a' and 'b' are within a valid range for multiplication. | ||
var lta; | ||
var ltb; | ||
|
||
lta = LessEqThan(252)([a, 2 ** 126]); | ||
ltb = LessEqThan(252)([b, 2 ** 126]); | ||
|
||
assert(lta == 1); | ||
assert(ltb == 1); | ||
|
||
// Perform integer division after multiplication to adjust the result back to W decimal digits. | ||
c <== IntegerDivision(n)(a * b, 10 ** W); | ||
} | ||
|
||
// Performs multiplication on integers by first converting them to floating-point representation. | ||
template MultiplicationFromNormal(W, n) { | ||
// Multiplicand. | ||
signal input a; | ||
// Multiplier. | ||
signal input b; | ||
// Product. | ||
signal output c; | ||
|
||
// Convert input to float and perform multiplication. | ||
c <== MultiplicationFromFloat(W, n)(ToFloat(W)(a), ToFloat(W)(b)); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
pragma circom 2.0.0; | ||
|
||
include "./bitify.circom"; | ||
|
||
// Template for safely comparing if one input is less than another, | ||
// ensuring inputs are within a specified bit-length. | ||
template SafeLessThan(n) { | ||
// Ensure the bit-length does not exceed 252 bits. | ||
assert(n <= 252); | ||
|
||
signal input in[2]; | ||
signal output out; | ||
|
||
// Convert both inputs to their bit representations to ensure | ||
// they fit within 'n' bits. | ||
var n2b1[n]; | ||
n2b1 = Num2Bits(n)(in[0]); | ||
|
||
var n2b2[n]; | ||
n2b2 = Num2Bits(n)(in[1]); | ||
|
||
// Additional conversion to handle arithmetic operation and capture the comparison result. | ||
var n2b[n+1]; | ||
n2b = Num2Bits(n + 1)(in[0] + (1<<n) - in[1]); | ||
|
||
// Determine if in[0] is less than in[1] based on the most significant bit. | ||
out <== 1 - n2b[n]; | ||
} | ||
|
||
// Template to check if one input is less than or equal to another. | ||
template SafeLessEqThan(n) { | ||
signal input in[2]; | ||
signal output out; | ||
|
||
// Use SafeLessThan to determine if in[0] is less than in[1] + 1. | ||
out <== SafeLessThan(n)([in[0], in[1] + 1]); | ||
} | ||
|
||
// Template for safely comparing if one input is greater than another. | ||
template SafeGreaterThan(n) { | ||
// Two inputs to compare. | ||
signal input in[2]; | ||
// Output signal indicating comparison result. | ||
signal output out; | ||
|
||
// Invert the inputs for SafeLessThan to check if in[1] is less than in[0]. | ||
out <== SafeLessThan(n)([in[1], in[0]]); | ||
} | ||
|
||
// Template to check if one input is greater than or equal to another. | ||
template SafeGreaterEqThan(n) { | ||
// Two inputs to compare. | ||
signal input in[2]; | ||
// Output signal indicating comparison result. | ||
signal output out; | ||
|
||
// Invert the inputs and adjust for equality in SafeLessThan to | ||
// check if in[1] is less than or equal to in[0]. | ||
out <== SafeLessThan(n)([in[1], in[0] + 1]); | ||
} |
Oops, something went wrong.