mirror of
https://github.com/selfxyz/self.git
synced 2026-04-05 03:00:53 -04:00
clean unused templates
This commit is contained in:
@@ -5,7 +5,6 @@ include "circomlib/circuits/bitify.circom";
|
||||
include "./bigIntFunc.circom";
|
||||
include "./bigIntOverflow.circom";
|
||||
include "../int/arithmetic.circom";
|
||||
include "./karatsuba.circom";
|
||||
|
||||
// What BigInt in this lib means
|
||||
// We represent big number as array of chunks with some shunk_size (will be explained later)
|
||||
@@ -20,193 +19,6 @@ include "./karatsuba.circom";
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
// Get sum of each chunk with same positions
|
||||
// out has overflow
|
||||
template BigAddNoCarry(CHUNK_SIZE, CHUNK_NUMBER){
|
||||
assert(CHUNK_SIZE <= 253);
|
||||
|
||||
signal input in[2][CHUNK_NUMBER];
|
||||
signal output out[CHUNK_NUMBER];
|
||||
|
||||
for (var i = 0; i < CHUNK_NUMBER; i++){
|
||||
out[i] <== in[0][i] + in[1][i];
|
||||
}
|
||||
}
|
||||
|
||||
// Get sum of each chunk with same positions
|
||||
// out has no overflow and has CHUNK_NUMBER + 1 chunks
|
||||
template BigAdd(CHUNK_SIZE, CHUNK_NUMBER){
|
||||
|
||||
signal input in[2][CHUNK_NUMBER];
|
||||
signal output out[CHUNK_NUMBER + 1];
|
||||
|
||||
component bigAddNoCarry = BigAddNoCarry(CHUNK_SIZE, CHUNK_NUMBER);
|
||||
bigAddNoCarry.in <== in;
|
||||
|
||||
component num2bits[CHUNK_NUMBER];
|
||||
|
||||
for (var i = 0; i < CHUNK_NUMBER; i++){
|
||||
num2bits[i] = Num2Bits(CHUNK_SIZE + 2);
|
||||
|
||||
//if >= 2**CHUNK_SIZE, overflow
|
||||
if (i == 0){
|
||||
num2bits[i].in <== bigAddNoCarry.out[i];
|
||||
} else {
|
||||
num2bits[i].in <== bigAddNoCarry.out[i] + num2bits[i - 1].out[CHUNK_SIZE];
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < CHUNK_NUMBER; i++){
|
||||
if (i == 0) {
|
||||
out[i] <== bigAddNoCarry.out[i] - (num2bits[i].out[CHUNK_SIZE]) * (2 ** CHUNK_SIZE);
|
||||
}
|
||||
else {
|
||||
out[i] <== bigAddNoCarry.out[i] - (num2bits[i].out[CHUNK_SIZE]) * (2 ** CHUNK_SIZE) + num2bits[i - 1].out[CHUNK_SIZE];
|
||||
}
|
||||
}
|
||||
out[CHUNK_NUMBER] <== num2bits[CHUNK_NUMBER - 1].out[CHUNK_SIZE];
|
||||
}
|
||||
|
||||
// get multiplication of 2 numbers with CHUNK_NUMBER chunks
|
||||
// out is 2 * CHUNK_NUMBER - 1 chunks with overflows
|
||||
template BigMultNoCarry(CHUNK_SIZE, CHUNK_NUMBER){
|
||||
|
||||
assert(CHUNK_SIZE <= 126);
|
||||
|
||||
signal input in[2][CHUNK_NUMBER];
|
||||
signal output out[CHUNK_NUMBER * 2 - 1];
|
||||
|
||||
signal tmpMults[CHUNK_NUMBER][CHUNK_NUMBER];
|
||||
for (var i = 0; i < CHUNK_NUMBER; i++){
|
||||
for (var j = 0; j < CHUNK_NUMBER; j++){
|
||||
tmpMults[i][j] <== in[0][i] * in[1][j];
|
||||
}
|
||||
}
|
||||
|
||||
// left - in[0][idx], right - in[1][idx]
|
||||
// 0*0 0*1 ... 0*n
|
||||
// 1*0 1*1 ... 1*n
|
||||
// ⋮ ⋮ \ ⋮
|
||||
// n*0 n*1 ... n*n
|
||||
//
|
||||
// result[idx].length = count(i+j === idx)
|
||||
// result[0].length = 1 (i = 0; j = 0)
|
||||
// result[1].length = 2 (i = 1; j = 0; i = 0; j = 1);
|
||||
// result[i].length = result[i-1].length + 1 if i <= CHUNK_NUMBER else result[i-1].length - 1 (middle, main diagonal)
|
||||
|
||||
signal tmpResult[CHUNK_NUMBER * 2 - 1][CHUNK_NUMBER];
|
||||
|
||||
for (var i = 0; i < CHUNK_NUMBER * 2 - 1; i++){
|
||||
|
||||
if (i < CHUNK_NUMBER){
|
||||
for (var j = 0; j < i + 1; j++){
|
||||
if (j == 0){
|
||||
tmpResult[i][j] <== tmpMults[i - j][j];
|
||||
} else {
|
||||
tmpResult[i][j] <== tmpMults[i - j][j] + tmpResult[i][j - 1];
|
||||
}
|
||||
}
|
||||
out[i] <== tmpResult[i][i];
|
||||
|
||||
} else {
|
||||
for (var j = 0; j < 2 * CHUNK_NUMBER - 1 - i; j++){
|
||||
if (j == 0){
|
||||
tmpResult[i][j] <== tmpMults[CHUNK_NUMBER - 1 - j][i + j - CHUNK_NUMBER + 1];
|
||||
} else {
|
||||
tmpResult[i][j] <== tmpMults[CHUNK_NUMBER - 1 - j][i + j - CHUNK_NUMBER + 1] + tmpResult[i][j - 1];
|
||||
}
|
||||
}
|
||||
out[i] <== tmpResult[i][2 * CHUNK_NUMBER - 2 - i];
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// get multiplication of 2 numbers with CHUNK_NUMBER chunks
|
||||
// out is 2 * CHUNK_NUMBER chunks without overflows
|
||||
template BigMult(CHUNK_SIZE, CHUNK_NUMBER){
|
||||
|
||||
signal input in[2][CHUNK_NUMBER];
|
||||
|
||||
|
||||
signal output out[CHUNK_NUMBER * 2];
|
||||
|
||||
component bigMultNoCarry = BigMultNoCarry(CHUNK_SIZE, CHUNK_NUMBER);
|
||||
bigMultNoCarry.in <== in;
|
||||
|
||||
component num2bits[CHUNK_NUMBER * 2 - 1];
|
||||
component bits2numOverflow[CHUNK_NUMBER * 2 - 1];
|
||||
component bits2numModulus[CHUNK_NUMBER * 2 - 1];
|
||||
|
||||
//overflow = no carry (multiplication result / 2 ** chunk_size) === chunk_size first bits in result
|
||||
for (var i = 0; i < 2 * CHUNK_NUMBER - 1; i++){
|
||||
//bigMultNoCarry = CHUNK_i * CHUNK_j (2 * CHUNK_SIZE) + CHUNK_i0 * CHUNK_j0 (2 * CHUNK_SIZE) + ..., up to len times,
|
||||
// => 2 * CHUNK_SIZE + ADDITIONAL_LEN
|
||||
var ADDITIONAL_LEN = i;
|
||||
if (i >= CHUNK_NUMBER){
|
||||
ADDITIONAL_LEN = 2 * CHUNK_NUMBER - 2 - i;
|
||||
}
|
||||
|
||||
num2bits[i] = Num2Bits(CHUNK_SIZE * 2 + ADDITIONAL_LEN);
|
||||
|
||||
if (i == 0){
|
||||
num2bits[i].in <== bigMultNoCarry.out[i];
|
||||
} else {
|
||||
num2bits[i].in <== bigMultNoCarry.out[i] + bits2numOverflow[i - 1].out;
|
||||
}
|
||||
|
||||
bits2numOverflow[i] = Bits2Num(CHUNK_SIZE + ADDITIONAL_LEN);
|
||||
for (var j = 0; j < CHUNK_SIZE + ADDITIONAL_LEN; j++){
|
||||
bits2numOverflow[i].in[j] <== num2bits[i].out[CHUNK_SIZE + j];
|
||||
}
|
||||
|
||||
bits2numModulus[i] = Bits2Num(CHUNK_SIZE);
|
||||
for (var j = 0; j < CHUNK_SIZE; j++){
|
||||
bits2numModulus[i].in[j] <== num2bits[i].out[j];
|
||||
}
|
||||
}
|
||||
for (var i = 0; i < 2 * CHUNK_NUMBER; i++){
|
||||
if (i == 2 * CHUNK_NUMBER - 1){
|
||||
out[i] <== bits2numOverflow[i - 1].out;
|
||||
} else {
|
||||
out[i] <== bits2numModulus[i].out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// same as previous one
|
||||
// using karatsuba multiplication under the hood
|
||||
// use only for CHUNK_NUMBER == 2 ** x
|
||||
template BigMultOptimised(CHUNK_SIZE, CHUNK_NUMBER){
|
||||
|
||||
signal input in[2][CHUNK_NUMBER];
|
||||
signal output out[CHUNK_NUMBER * 2];
|
||||
|
||||
component karatsuba = KaratsubaNoCarry(CHUNK_NUMBER);
|
||||
karatsuba.in <== in;
|
||||
|
||||
|
||||
component getLastNBits[CHUNK_NUMBER * 2 - 1];
|
||||
component bits2Num[CHUNK_NUMBER * 2 - 1];
|
||||
|
||||
for (var i = 0; i < CHUNK_NUMBER * 2 - 1; i++){
|
||||
getLastNBits[i] = GetLastNBits(CHUNK_SIZE);
|
||||
bits2Num[i] = Bits2Num(CHUNK_SIZE);
|
||||
|
||||
if (i == 0) {
|
||||
getLastNBits[i].in <== karatsuba.out[i];
|
||||
} else {
|
||||
getLastNBits[i].in <== karatsuba.out[i] + getLastNBits[i - 1].div;
|
||||
}
|
||||
bits2Num[i].in <== getLastNBits[i].out;
|
||||
}
|
||||
|
||||
for (var i = 0; i < CHUNK_NUMBER * 2 - 1; i++){
|
||||
out[i] <== bits2Num[i].out;
|
||||
}
|
||||
out[CHUNK_NUMBER * 2 - 1] <== getLastNBits[CHUNK_NUMBER * 2 - 2].div;
|
||||
}
|
||||
|
||||
// Get in1 * in2 % modulus and in1 * in2 // modulus
|
||||
template BigMultModP(CHUNK_SIZE, CHUNK_NUMBER_GREATER, CHUNK_NUMBER_LESS, CHUNK_NUMBER_MODULUS){
|
||||
signal input in1[CHUNK_NUMBER_GREATER];
|
||||
@@ -267,195 +79,6 @@ template BigMultModP(CHUNK_SIZE, CHUNK_NUMBER_GREATER, CHUNK_NUMBER_LESS, CHUNK_
|
||||
}
|
||||
}
|
||||
|
||||
// substition of 2 nums with CHUNK_NUMBER
|
||||
// out is CHUNK_NUMBER with overflows
|
||||
// don`t use this one outside the BigSub without knowing what are u doing!!!
|
||||
template BigSubNoBorrow(CHUNK_SIZE, CHUNK_NUMBER){
|
||||
assert (CHUNK_SIZE < 252);
|
||||
|
||||
signal input in[2][CHUNK_NUMBER];
|
||||
signal output out[CHUNK_NUMBER];
|
||||
|
||||
for (var i = 0; i < CHUNK_NUMBER; i++){
|
||||
out[i] <== in[0][i] - in[1][i];
|
||||
}
|
||||
}
|
||||
|
||||
// in[0] >= in[1], else will not work correctly, use only in this case!
|
||||
// substition of 2 nums with CHUNK_NUMBER
|
||||
// out is CHUNK_NUMBER without overflows
|
||||
template BigSub(CHUNK_SIZE, CHUNK_NUMBER){
|
||||
signal input in[2][CHUNK_NUMBER];
|
||||
signal output out[CHUNK_NUMBER];
|
||||
component bigSubNoBorrow = BigSubNoBorrow(CHUNK_SIZE, CHUNK_NUMBER);
|
||||
bigSubNoBorrow.in <== in;
|
||||
|
||||
component lessThan[CHUNK_NUMBER];
|
||||
for (var i = 0; i < CHUNK_NUMBER; i++){
|
||||
lessThan[i] = LessThan(CHUNK_SIZE + 1);
|
||||
lessThan[i].in[1] <== 2 ** CHUNK_SIZE;
|
||||
|
||||
if (i == 0){
|
||||
lessThan[i].in[0] <== bigSubNoBorrow.out[i] + 2 ** CHUNK_SIZE;
|
||||
out[i] <== bigSubNoBorrow.out[i] + (2 ** CHUNK_SIZE) * (lessThan[i].out);
|
||||
} else {
|
||||
lessThan[i].in[0] <== bigSubNoBorrow.out[i] - lessThan[i - 1].out + 2 ** CHUNK_SIZE;
|
||||
out[i] <== bigSubNoBorrow.out[i] + (2 ** CHUNK_SIZE) * (lessThan[i].out) - lessThan[i - 1].out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// get multiplication of 2 numbers with CHUNK_NUMBER_GREATER and CHUNK_NUMBER_LESS chunks
|
||||
// in1 have CHUNK_NUMBER_GREATER chunks, in2 - CHUNK_NUMBER_LESS
|
||||
// out is CHUNK_NUMBER_GREATER + CHUNK_NUMBER_LESS - 1 chunks with overflows
|
||||
template BigMultNoCarryNonEqual(CHUNK_SIZE, CHUNK_NUMBER_GREATER, CHUNK_NUMBER_LESS){
|
||||
|
||||
assert(CHUNK_NUMBER_GREATER + CHUNK_NUMBER_LESS <= 252);
|
||||
assert(CHUNK_NUMBER_GREATER >= CHUNK_NUMBER_LESS);
|
||||
|
||||
signal input in1[CHUNK_NUMBER_GREATER];
|
||||
signal input in2[CHUNK_NUMBER_LESS];
|
||||
signal output out[CHUNK_NUMBER_GREATER + CHUNK_NUMBER_LESS - 1];
|
||||
|
||||
|
||||
// We can`t mult multiply 2 big nums without multiplying each chunks of first with each chunk of second
|
||||
|
||||
signal tmpMults[CHUNK_NUMBER_GREATER][CHUNK_NUMBER_LESS];
|
||||
for (var i = 0; i < CHUNK_NUMBER_GREATER; i++){
|
||||
for (var j = 0; j < CHUNK_NUMBER_LESS; j++){
|
||||
tmpMults[i][j] <== in1[i] * in2[j];
|
||||
}
|
||||
}
|
||||
|
||||
// left - in1[idx], right - in2[idx] || n - CHUNK_NUMBER_GREATER, m - CHUNK_NUMBER_LESS
|
||||
// 0*0 0*1 ... 0*n
|
||||
// 1*0 1*1 ... 1*n
|
||||
// ⋮ ⋮ \ ⋮
|
||||
// m*0 m*1 ... m*n
|
||||
//
|
||||
// result[idx].length = count(i+j === idx)
|
||||
// result[0].length = 1 (i = 0; j = 0)
|
||||
// result[1].length = 2 (i = 1; j = 0; i = 0; j = 1);
|
||||
// result[i].length = { result[i-1].length + 1, i <= CHUNK_NUMBER_LESS}
|
||||
// { result[i-1].length - 1, i > CHUNK_NUMBER_GREATER}
|
||||
// { result[i-1].length, CHUNK_NUMBER_LESS < i <= CHUNK_NUMBER_GREATER}
|
||||
|
||||
signal tmpResult[CHUNK_NUMBER_GREATER + CHUNK_NUMBER_LESS - 1][CHUNK_NUMBER_LESS];
|
||||
|
||||
for (var i = 0; i < CHUNK_NUMBER_GREATER + CHUNK_NUMBER_LESS - 1; i++){
|
||||
|
||||
if (i < CHUNK_NUMBER_LESS){
|
||||
for (var j = 0; j < i + 1; j++){
|
||||
if (j == 0){
|
||||
tmpResult[i][j] <== tmpMults[i - j][j];
|
||||
} else {
|
||||
tmpResult[i][j] <== tmpMults[i - j][j] + tmpResult[i][j - 1];
|
||||
}
|
||||
}
|
||||
out[i] <== tmpResult[i][i];
|
||||
|
||||
} else {
|
||||
if (i < CHUNK_NUMBER_GREATER) {
|
||||
for (var j = 0; j < CHUNK_NUMBER_LESS; j++){
|
||||
if (j == 0){
|
||||
tmpResult[i][j] <== tmpMults[i - j][j];
|
||||
} else {
|
||||
tmpResult[i][j] <== tmpMults[i - j][j] + tmpResult[i][j - 1];
|
||||
}
|
||||
}
|
||||
out[i] <== tmpResult[i][CHUNK_NUMBER_LESS - 1];
|
||||
} else {
|
||||
for (var j = 0; j < CHUNK_NUMBER_GREATER + CHUNK_NUMBER_LESS - 1 - i; j++){
|
||||
if (j == 0){
|
||||
tmpResult[i][j] <== tmpMults[CHUNK_NUMBER_GREATER - 1 - j][i + j - CHUNK_NUMBER_GREATER + 1];
|
||||
} else {
|
||||
tmpResult[i][j] <== tmpMults[CHUNK_NUMBER_GREATER - 1 - j][i + j - CHUNK_NUMBER_GREATER + 1] + tmpResult[i][j - 1];
|
||||
}
|
||||
}
|
||||
out[i] <== tmpResult[i][CHUNK_NUMBER_GREATER + CHUNK_NUMBER_LESS - 2 - i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// get multiplication of 2 numbers with CHUNK_NUMBER_GREATER and CHUNK_NUMBER_LESS chunks
|
||||
// in1 have CHUNK_NUMBER_GREATER chunks, in2 - CHUNK_NUMBER_LESS
|
||||
// out is CHUNK_NUMBER_GREATER + CHUNK_NUMBER_LESS chunks with overflows
|
||||
// automatic usage of otimised multiplication if CHUNK_NUMBER_GREATER == 2 ** k (karatsuba)
|
||||
template BigMultNonEqual(CHUNK_SIZE, CHUNK_NUMBER_GREATER, CHUNK_NUMBER_LESS){
|
||||
|
||||
signal input in1[CHUNK_NUMBER_GREATER];
|
||||
signal input in2[CHUNK_NUMBER_LESS];
|
||||
signal output out[CHUNK_NUMBER_GREATER + CHUNK_NUMBER_LESS];
|
||||
var isPowerOfTwo = 0;
|
||||
for (var i = 0; i < CHUNK_NUMBER_GREATER; i++){
|
||||
if (CHUNK_NUMBER_GREATER == 2 ** i){
|
||||
isPowerOfTwo = 1;
|
||||
}
|
||||
}
|
||||
if (isPowerOfTwo == 0){
|
||||
|
||||
component bigMultNoCarry = BigMultNoCarryNonEqual(CHUNK_SIZE, CHUNK_NUMBER_GREATER, CHUNK_NUMBER_LESS);
|
||||
bigMultNoCarry.in1 <== in1;
|
||||
bigMultNoCarry.in2 <== in2;
|
||||
|
||||
component num2bits[CHUNK_NUMBER_GREATER + CHUNK_NUMBER_LESS - 1];
|
||||
component bits2numOverflow[CHUNK_NUMBER_GREATER + CHUNK_NUMBER_LESS - 1];
|
||||
component bits2numModulus[CHUNK_NUMBER_GREATER + CHUNK_NUMBER_LESS - 1];
|
||||
|
||||
//overflow = no carry (multiplication result / 2 ** chunk_size) === chunk_size first bits in result
|
||||
for (var i = 0; i < CHUNK_NUMBER_GREATER + CHUNK_NUMBER_LESS - 1; i++){
|
||||
//bigMultNoCarry = CHUNK_i * CHUNK_j (2 * CHUNK_SIZE) + CHUNK_i0 * CHUNK_j0 (2 * CHUNK_SIZE) + ..., up to len times,
|
||||
// => 2 * CHUNK_SIZE + ADDITIONAL_LEN
|
||||
var ADDITIONAL_LEN = i;
|
||||
if (i >= CHUNK_NUMBER_LESS){
|
||||
ADDITIONAL_LEN = CHUNK_NUMBER_LESS - 1;
|
||||
}
|
||||
if (i >= CHUNK_NUMBER_GREATER){
|
||||
ADDITIONAL_LEN = CHUNK_NUMBER_GREATER + CHUNK_NUMBER_LESS - 1 - i;
|
||||
}
|
||||
|
||||
|
||||
num2bits[i] = Num2Bits(CHUNK_SIZE * 2 + ADDITIONAL_LEN);
|
||||
|
||||
if (i == 0){
|
||||
num2bits[i].in <== bigMultNoCarry.out[i];
|
||||
} else {
|
||||
num2bits[i].in <== bigMultNoCarry.out[i] + bits2numOverflow[i - 1].out;
|
||||
}
|
||||
|
||||
bits2numOverflow[i] = Bits2Num(CHUNK_SIZE + ADDITIONAL_LEN);
|
||||
for (var j = 0; j < CHUNK_SIZE + ADDITIONAL_LEN; j++){
|
||||
bits2numOverflow[i].in[j] <== num2bits[i].out[CHUNK_SIZE + j];
|
||||
}
|
||||
|
||||
bits2numModulus[i] = Bits2Num(CHUNK_SIZE);
|
||||
for (var j = 0; j < CHUNK_SIZE; j++){
|
||||
bits2numModulus[i].in[j] <== num2bits[i].out[j];
|
||||
}
|
||||
}
|
||||
for (var i = 0; i < CHUNK_NUMBER_GREATER + CHUNK_NUMBER_LESS; i++){
|
||||
if (i == CHUNK_NUMBER_GREATER + CHUNK_NUMBER_LESS - 1){
|
||||
out[i] <== bits2numOverflow[i - 1].out;
|
||||
} else {
|
||||
out[i] <== bits2numModulus[i].out;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
component bigMult = BigMultOptimised(CHUNK_SIZE, CHUNK_NUMBER_GREATER);
|
||||
for (var i = 0; i < CHUNK_NUMBER_LESS; i++){
|
||||
bigMult.in[0][i] <== in1[i];
|
||||
bigMult.in[1][i] <== in2[i];
|
||||
}
|
||||
for (var i = CHUNK_NUMBER_LESS; i < CHUNK_NUMBER_GREATER; i++){
|
||||
bigMult.in[0][i] <== in1[i];
|
||||
bigMult.in[1][i] <== 0;
|
||||
}
|
||||
for (var i = 0; i < CHUNK_NUMBER_LESS + CHUNK_NUMBER_GREATER; i++){
|
||||
out[i] <== bigMult.out[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// in[0] <= in[1]
|
||||
template BigLessEqThan(CHUNK_SIZE, CHUNK_NUMBER){
|
||||
|
||||
@@ -68,29 +68,6 @@ template BigMultOverflow(CHUNK_SIZE, CHUNK_NUMBER_GREATER, CHUNK_NUMBER_LESS){
|
||||
}
|
||||
}
|
||||
|
||||
// computes modulus + in1 - in2 (WITHOUT % modulus!!!) with overflows, in1 and in2 shouldn`t have overflows and in1 < modulus, in2 < modulus!
|
||||
// use only if you undestand what are you doing!!!
|
||||
// Use case if (a * b - c) % p, here u can use (a * b + (p + p - c) % p)
|
||||
template BigSubModOverflow(CHUNK_SIZE, CHUNK_NUMBER){
|
||||
signal input in1[CHUNK_NUMBER];
|
||||
signal input in2[CHUNK_NUMBER];
|
||||
signal input modulus[CHUNK_NUMBER];
|
||||
|
||||
signal output out[CHUNK_NUMBER];
|
||||
|
||||
for (var i = 0; i < CHUNK_NUMBER; i++){
|
||||
if (i == 0){
|
||||
out[i] <== 2 ** CHUNK_SIZE + modulus[i] + in1[i] - in2[i];
|
||||
} else {
|
||||
if (i == CHUNK_NUMBER - 1){
|
||||
out[i] <== modulus[i] + in1[i] - in2[i] - 1;
|
||||
} else {
|
||||
out[i] <== 2 ** CHUNK_SIZE + modulus[i] + in1[i] - in2[i] - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// multiplying number with CHUNK_NUMBER by scalar, ignoring overflow
|
||||
template ScalarMultOverflow(CHUNK_NUMBER){
|
||||
signal input in[CHUNK_NUMBER];
|
||||
@@ -123,28 +100,4 @@ template BigSubModP(CHUNK_SIZE, CHUNK_NUMBER){
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// USE ONLY if u sure it will not affect your security, because it is possible to get 1 in out with non-equal inputs, be carefull with it!!!
|
||||
// this compares one chunk representation of nums, and if they are bigger than circom curve prime (~2**254), it will compare modulus by it
|
||||
// it always uses 4 constraints and allows to always get 1 for equal inputs
|
||||
// there is a way to get "collision" and get 1 for non equal chunks, however
|
||||
// it almost impossible to get it randomly (almost the same as hash sha-256 collision), but it can be calculated
|
||||
// it still doesn`t allowed to put anything that u want at witness and get valid proof, so it shouldn`t affect on security if it is one of many cheks in your circuit
|
||||
template SmartEqual(CHUNK_SIZE, CHUNK_NUMBER){
|
||||
signal input in[2][CHUNK_NUMBER];
|
||||
signal output out;
|
||||
component isEqual = IsEqual();
|
||||
component sumLeft = GetSumOfNElements(CHUNK_NUMBER);
|
||||
component sumRight = GetSumOfNElements(CHUNK_NUMBER);
|
||||
|
||||
for (var i = 0; i < CHUNK_NUMBER; i++){
|
||||
sumLeft.in[i] <== 2 ** (i * CHUNK_SIZE) * in[0][i];
|
||||
sumRight.in[i] <== 2 ** (i * CHUNK_SIZE) * in[1][i];
|
||||
}
|
||||
|
||||
isEqual.in[0] <== sumLeft.out;
|
||||
isEqual.in[1] <== sumRight.out;
|
||||
|
||||
out <== isEqual.out;
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
pragma circom 2.1.6;
|
||||
|
||||
// Calculates 2 numbers with CHUNK_NUMBER multiplication using karatsuba method
|
||||
// out is overflowed
|
||||
// use only for 2 ** k CHUNK_NUMBER, othewise u will get error
|
||||
// here is no check for CHUNK_SIZE <= 126, maybe will be added later
|
||||
template KaratsubaNoCarry(CHUNK_NUMBER) {
|
||||
signal input in[2][CHUNK_NUMBER];
|
||||
signal output out[2 * CHUNK_NUMBER];
|
||||
|
||||
if (CHUNK_NUMBER == 1) {
|
||||
out[0] <== in[0][0] * in[1][0];
|
||||
} else {
|
||||
component karatsubaA1B1 = KaratsubaNoCarry(CHUNK_NUMBER / 2);
|
||||
component karatsubaA2B2 = KaratsubaNoCarry(CHUNK_NUMBER / 2);
|
||||
component karatsubaA1A2B1B2 = KaratsubaNoCarry(CHUNK_NUMBER / 2);
|
||||
|
||||
for (var i = 0; i < CHUNK_NUMBER / 2; i++) {
|
||||
karatsubaA1B1.in[0][i] <== in[0][i];
|
||||
karatsubaA1B1.in[1][i] <== in[1][i];
|
||||
karatsubaA2B2.in[0][i] <== in[0][i + CHUNK_NUMBER / 2];
|
||||
karatsubaA2B2.in[1][i] <== in[1][i + CHUNK_NUMBER / 2];
|
||||
karatsubaA1A2B1B2.in[0][i] <== in[0][i] + in[0][i + CHUNK_NUMBER / 2];
|
||||
karatsubaA1A2B1B2.in[1][i] <== in[1][i] + in[1][i + CHUNK_NUMBER / 2];
|
||||
}
|
||||
|
||||
for (var i = 0; i < 2 * CHUNK_NUMBER; i++) {
|
||||
if (i < CHUNK_NUMBER) {
|
||||
if (CHUNK_NUMBER / 2 <= i && i < 3 * (CHUNK_NUMBER / 2)) {
|
||||
out[i] <== karatsubaA1B1.out[i]
|
||||
+ karatsubaA1A2B1B2.out[i - CHUNK_NUMBER / 2]
|
||||
- karatsubaA1B1.out[i - CHUNK_NUMBER / 2]
|
||||
- karatsubaA2B2.out[i - CHUNK_NUMBER / 2];
|
||||
} else {
|
||||
out[i] <== karatsubaA1B1.out[i];
|
||||
}
|
||||
} else {
|
||||
if (CHUNK_NUMBER / 2 <= i && i < 3 * (CHUNK_NUMBER / 2)) {
|
||||
out[i] <== karatsubaA2B2.out[i - CHUNK_NUMBER]
|
||||
+ karatsubaA1A2B1B2.out[i - CHUNK_NUMBER / 2]
|
||||
- karatsubaA1B1.out[i - CHUNK_NUMBER / 2]
|
||||
- karatsubaA2B2.out[i - CHUNK_NUMBER / 2];
|
||||
} else {
|
||||
out[i] <== karatsubaA2B2.out[i - CHUNK_NUMBER];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,75 +1,6 @@
|
||||
|
||||
pragma circom 2.1.6;
|
||||
|
||||
/// @title EllipticCurveGetGenerator
|
||||
/// @notice Returns the generator point for a given elliptic curve defined by parameters A, B, and P.
|
||||
/// @param CHUNK_SIZE The size of each chunk for the scalar multiplication.
|
||||
/// @param CHUNK_NUMBER The number of chunks used in the scalar multiplication.
|
||||
/// @param A The parameter A of the elliptic curve equation.
|
||||
/// @param B The parameter B of the elliptic curve equation.
|
||||
/// @param P The curve's prime field parameter.
|
||||
/// @return gen The generator point for the elliptic curve, with coordinates in the field represented by two arrays of CHUNK_NUMBER elements.
|
||||
template EllipticCurveGetGenerator(CHUNK_SIZE, CHUNK_NUMBER, A, B, P){
|
||||
signal output gen[2][CHUNK_NUMBER];
|
||||
|
||||
if (CHUNK_NUMBER == 4){
|
||||
if (P[0] == 2311270323689771895 && P[1] == 7943213001558335528 && P[2] == 4496292894210231666 && P[3] == 12248480212390422972){
|
||||
gen[0] <== [4198572826427273826, 13393186192988382146, 3191724131859150767, 10075307429387458507];
|
||||
gen[1] <== [6637554640278022551, 14012744714263826004, 10950579571776363977, 6088576656054338813];
|
||||
}
|
||||
if (P[0] == 18446744073709551615 && P[1] == 4294967295 && P[2] == 0 && P[3] == 18446744069414584321) {
|
||||
gen[0] <== [17627433388654248598, 8575836109218198432, 17923454489921339634, 7716867327612699207];
|
||||
gen[1] <== [14678990851816772085, 3156516839386865358, 10297457778147434006, 5756518291402817435];
|
||||
}
|
||||
}
|
||||
if (CHUNK_NUMBER == 6){
|
||||
if (P[0] == 4294967295 && P[1] == 18446744069414584320 && P[2] == 18446744073709551614 && P[3] == 18446744073709551615 && P[4] == 18446744073709551615 && P[5] == 18446744073709551615){
|
||||
gen[0] <== [4203087948775033527, 6125724927633205612, 6482722621138151992, 7934563412932533144, 10282218360005504372, 12288012358878168375];
|
||||
gen[1] <== [8809917716911230559, 747793036959711645, 16850834916486723776, 17938995913990739068, 6745997240412855337, 3897828414440483951];
|
||||
}
|
||||
if (P[0] == 9747760000893709395 && P[1] == 12453481191562877553 && P[2] == 1347097566612230435 && P[3] == 1526563086152259252 && P[4] == 1107163671716839903 && P[5] == 10140169582434348328){
|
||||
gen[0] <== [17259960781858189086, 16728304380777219754, 15816583608832692456, 9819997727167172579, 11720119409086381931, 2097662510161151487];
|
||||
gen[1] <== [4792396531824874261, 1028586674454626577, 16256874595948243240, 7113166411453454436, 6679378719998465362, 9997460611710698148];
|
||||
}
|
||||
|
||||
}
|
||||
if (CHUNK_NUMBER == 8 && CHUNK_SIZE == 64){
|
||||
if (P[0] == 2930260431521597683 && P[1] == 2918894611604883077 && P[2] == 12595900938455318758 && P[3] == 9029043254863489090 && P[4] == 15448363540090652785 && P[5] == 14641358191536493070 && P[6] == 4599554755319692295 && P[7] == 12312170373589877899){
|
||||
gen[0] <== [10030961170254002210, 8965910700118138472, 5823550673135435103, 18391328107359425677, 12987082728901970318, 9650544882960897729, 6494527313417104019, 9344657780867258724];
|
||||
gen[1] <== [8704646705537616018, 15116942582920270854, 6614182396149851054, 12888420639989254238, 11529432042984931601, 17440742611955841818, 13901133935883592445, 9069748673103213292];
|
||||
}
|
||||
}
|
||||
|
||||
if (CHUNK_NUMBER == 8 && CHUNK_SIZE == 66){
|
||||
if (P[0] == 73786976294838206463 && P[1] == 73786976294838206463 && P[2] == 73786976294838206463 && P[3] == 73786976294838206463 && P[4] == 73786976294838206463 && P[5] == 73786976294838206463 && P[6] == 73786976294838206463 && P[7] == 576460752303423487){
|
||||
gen[0] <== [73318177735826586982, 65487454542484902054, 47261297936520182413, 53792451325664927076, 20894495204887448893, 19646699525969629165, 48195803493093751131, 223515561732870163];
|
||||
gen[1] <== [9853476271941576272, 5570702194968932496, 888629214913941622, 12853196140475830425, 7500656931080978022, 54648434146783127249, 19642388603652049, 315503374086858991];
|
||||
}
|
||||
}
|
||||
if (CHUNK_NUMBER == 7 && CHUNK_SIZE == 32){
|
||||
if (P[0] == 2127085823 && P[1] == 2547681781 && P[2] == 2963212119 && P[3] == 1976686471 && P[4] == 706228261 && P[5] == 641951366 && P[6] == 3619763370){
|
||||
gen[0] <== [3994206333, 1277062909, 2655838999, 2826815116, 872948658, 746478836, 227551661];
|
||||
gen[1] <== [1981022925, 3399743187, 894148249, 1322101796, 617003166, 1925214831, 1487558391];
|
||||
}
|
||||
if (P[0] == 1 && P[1] == 0 && P[2] == 0 && P[3] == 4294967295 && P[4] == 4294967295 && P[5] == 4294967295 && P[6] == 4294967295){
|
||||
gen[0] <== [291249441, 875725014, 1455558946, 1241760211, 840143033, 1807007615, 3071151293];
|
||||
gen[1] <== [2231402036, 1154843033, 1510426468, 3443750304, 1277353958, 3052872699, 3174523784];
|
||||
}
|
||||
}
|
||||
if (CHUNK_NUMBER == 5 && CHUNK_SIZE == 64){
|
||||
if (P[0] == 18218206948094062119 && P[1] == 5733849700882443304 && P[2] == 17982820153128390127 && P[3] == 16229979505782022245 && P[4] == 15230689193496432567){
|
||||
gen[0] <== [1202334713476417041, 16683336510634039751, 17438280603111292598, 5947492335316484070, 4881196775246125240];
|
||||
gen[1] <== [15227310055808208609, 12233879368135109319, 523543375370093290, 12340024763961780062, 1512594114530254024];
|
||||
}
|
||||
}
|
||||
if (CHUNK_NUMBER == 3 && CHUNK_SIZE == 64){
|
||||
if (P[0] == 18446744073709551615 && P[1] == 18446744073709551614 && P[2] == 18446744073709551615){
|
||||
gen[0] <== [17653841148256391186, 8988939576078862336, 1769255009665454326];
|
||||
gen[1] <== [8356842117447370769, 7138225120784731605, 511487955924736632];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// @title EllipticCurveGetDummy
|
||||
/// @notice Returns a "dummy" point on the elliptic curve. This dummy point is used to handle cases where operations are required but the result is not used.
|
||||
/// The dummy point is defined as G * 2^256, where G is the generator point of the elliptic curve.
|
||||
|
||||
Reference in New Issue
Block a user