Undo ecdsa changes

pull/4430/head^2
ioedeveloper 11 months ago committed by Aniket
parent 677ca5403d
commit 2077c92095
  1. 4
      apps/remix-ide/src/app/editor/editor.js
  2. 1
      apps/remix-ide/src/app/tabs/locales/en/filePanel.json
  3. 2
      libs/remix-ui/workspace/src/lib/actions/workspace.ts
  4. 3
      libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx
  5. 2
      libs/remix-ui/workspace/src/lib/types/index.ts
  6. 1
      libs/remix-ui/workspace/src/lib/utils/constants.ts
  7. 1
      libs/remix-ws-templates/src/index.ts
  8. 26
      libs/remix-ws-templates/src/templates/ecdsa/README.md
  9. 57
      libs/remix-ws-templates/src/templates/ecdsa/circuits/eff_ecdsa_membership/addr_membership.circom
  10. 39
      libs/remix-ws-templates/src/templates/ecdsa/circuits/eff_ecdsa_membership/eff_ecdsa.circom
  11. 42
      libs/remix-ws-templates/src/templates/ecdsa/circuits/eff_ecdsa_membership/eff_ecdsa_to_addr.circom
  12. 46
      libs/remix-ws-templates/src/templates/ecdsa/circuits/eff_ecdsa_membership/pubkey_membership.circom
  13. 125
      libs/remix-ws-templates/src/templates/ecdsa/circuits/eff_ecdsa_membership/secp256k1/add.circom
  14. 27
      libs/remix-ws-templates/src/templates/ecdsa/circuits/eff_ecdsa_membership/secp256k1/double.circom
  15. 190
      libs/remix-ws-templates/src/templates/ecdsa/circuits/eff_ecdsa_membership/secp256k1/mul.circom
  16. 183
      libs/remix-ws-templates/src/templates/ecdsa/circuits/eff_ecdsa_membership/to_address/vocdoni-keccak/keccak.circom
  17. 796
      libs/remix-ws-templates/src/templates/ecdsa/circuits/eff_ecdsa_membership/to_address/vocdoni-keccak/permutations.circom
  18. 115
      libs/remix-ws-templates/src/templates/ecdsa/circuits/eff_ecdsa_membership/to_address/vocdoni-keccak/utils.circom
  19. 91
      libs/remix-ws-templates/src/templates/ecdsa/circuits/eff_ecdsa_membership/to_address/zk-identity/eth.circom
  20. 48
      libs/remix-ws-templates/src/templates/ecdsa/circuits/eff_ecdsa_membership/tree.circom
  21. 5
      libs/remix-ws-templates/src/templates/ecdsa/circuits/instances/addr_membership.circom
  22. 5
      libs/remix-ws-templates/src/templates/ecdsa/circuits/instances/pubkey_membership.circom
  23. 158
      libs/remix-ws-templates/src/templates/ecdsa/circuits/poseidon/poseidon.circom
  24. 218
      libs/remix-ws-templates/src/templates/ecdsa/circuits/poseidon/poseidon_constants.circom
  25. 44
      libs/remix-ws-templates/src/templates/ecdsa/index.ts
  26. 56
      libs/remix-ws-templates/src/templates/ecdsa/scripts/run_setup.ts
  27. 122
      libs/remix-ws-templates/src/templates/ecdsa/scripts/run_verification.ts
  28. 165
      libs/remix-ws-templates/src/templates/ecdsa/templates/groth16_verifier.sol.ejs

@ -208,8 +208,8 @@ class Editor extends Plugin {
const paths = path.split('/')
paths.pop()
const fromPath = paths.join('/') // get current execution context path
for (const match of content.matchAll(/import\s+(?:(?:\{[^{}]*\}|[^'";]+)\s+from\s+)?['"](@[\w-]+\/[\w-]+)['"];?/g)) {
let pathDep = match[1]
for (const match of content.matchAll(/import\s+.*\s+from\s+(?:"(.*?)"|'(.*?)')/g)) {
let pathDep = match[2]
if (pathDep.startsWith('./') || pathDep.startsWith('../')) pathDep = resolve(fromPath, pathDep)
if (pathDep.startsWith('/')) pathDep = pathDep.substring(1)
if (!pathDep.endsWith('.ts')) pathDep = pathDep + '.ts'

@ -112,7 +112,6 @@
"filePanel.semaphore": "Semaphore",
"filePanel.hashchecker": "Hash Checker",
"filePanel.rln": "Rate-Limiting Nullifier",
"filePanel.ecdsa": "ECDSA (Elliptic Curve Digital Signature Algorithm)",
"filePanel.breakthroughLabsUniswapv4Hooks": "Breakthrough-Labs Hooks",
"filePanel.uniswapV4Periphery": "v4 Periphery",
"filePanel.uniswapV4HookBookMultiSigSwapHook": "HookBook MultiSigSwapHook",

@ -204,7 +204,7 @@ export const createWorkspace = async (
const isActive = await plugin.call('manager', 'isActive', 'dgit')
if (!isActive) await plugin.call('manager', 'activatePlugin', 'dgit')
}
if (workspaceTemplateName === 'semaphore' || workspaceTemplateName === 'hashchecker' || workspaceTemplateName === 'rln' || workspaceTemplateName === 'ecdsa') {
if (workspaceTemplateName === 'semaphore' || workspaceTemplateName === 'hashchecker' || workspaceTemplateName === 'rln') {
const isCircomActive = await plugin.call('manager', 'isActive', 'circuit-compiler')
if (!isCircomActive) await plugin.call('manager', 'activatePlugin', 'circuit-compiler')
}

@ -784,9 +784,6 @@ export function Workspace() {
<option style={{fontSize: 'small'}} value="rln">
{intl.formatMessage({id: 'filePanel.rln'})}
</option>
<option style={{fontSize: 'small'}} value="ecdsa">
{intl.formatMessage({id: 'filePanel.ecdsa'})}
</option>
</optgroup>
<optgroup style={{fontSize: 'medium'}} label="Uniswap V4">
<option style={{fontSize: 'small'}} value="uniswapV4Periphery">

@ -19,7 +19,7 @@ export interface JSONStandardInput {
}
}
export type MenuItems = action[]
export type WorkspaceTemplate = 'gist-template' | 'code-template' | 'remixDefault' | 'blank' | 'ozerc20' | 'zeroxErc20' | 'ozerc721' | 'playground' | 'semaphore' | 'hashchecker' | 'rln' | 'breakthroughLabsUniswapv4Hooks' | 'uniswapV4Periphery' | 'uniswapV4HookBookMultiSigSwapHook' | 'ecdsa'
export type WorkspaceTemplate = 'gist-template' | 'code-template' | 'remixDefault' | 'blank' | 'ozerc20' | 'zeroxErc20' | 'ozerc721' | 'playground' | 'semaphore' | 'hashchecker' | 'rln' | 'breakthroughLabsUniswapv4Hooks' | 'uniswapV4Periphery' | 'uniswapV4HookBookMultiSigSwapHook'
export interface WorkspaceProps {
plugin: FilePanelType
}

@ -89,7 +89,6 @@ export const TEMPLATE_NAMES = {
'breakthroughLabsUniswapv4Hooks': 'Breakthrough-Labs Uniswapv4Hooks',
'uniswapV4Periphery': 'Uniswap v4 Periphery',
'uniswapV4HookBookMultiSigSwapHook': 'Uniswap V4 HookBook MultiSigSwapHook',
'ecdsa': 'spartan-ecdsa'
}
export const TEMPLATE_METADATA: Record<string, TemplateType> = {

@ -9,7 +9,6 @@ export { default as playground } from './templates/playground'
export { default as semaphore } from './templates/semaphore'
export { default as hashchecker } from './templates/hashchecker'
export { default as rln } from './templates/rln'
export { default as ecdsa } from './templates/ecdsa'
export { contractDeployerScripts } from './script-templates/contract-deployer'
export { etherscanScripts } from './script-templates/etherscan'

@ -1,26 +0,0 @@
## CIRCOM ZKP SEMAPHORE WORKSPACE
Welcome to the Remix Circom ZKP Semaphore Workspace.
The workspace comprises two main directories:
### circuits: Contains sample semaphore contracts. These can be compiled to generate a witness using 'Circom ZKP Compiler' plugin.
### scripts: Provides a sample script designed for a trusted setup using snarkjs. This script also aids in generating Solidity code, which is essential for on-chain deployment.
### first steps:
#### 1) compile the semaphore circuit using the remix circom compiler. This will generate artifacts.
#### 2) execute the file `run_setup.ts`:
This step generate a verification key that can be used for generating proof, it will also generate a Solidity contract for on-chain verification.
Note that this section should only be used for development purposes as this way of running the setup is heavily centralized (although some pieces of this script can be used to achieve that).
This generates a verification key (`./zk/build/verification_key.json`) and artifacts from the setup (`./zk/build/zk_setup.txt`).
#### 3) execute the file `run_verification.ts`:
This script:
- create a list of identity commitments and add it to a `IncrementalMerkleTree`. The tree is used to generate a merkle proof that a specified identity is actually in the tree (see`tree.createProof(0)`).
- generate a witness and a proof of execution.
- verify that the proof is valid `(snarkjs.groth16.verify)`
- ultimately verify that the hash generated by the circom compiler is the same as the root hash for the Tree. `(proof1.root.toString() === publicSignals[0]`). This assert that the identity provided to the circuit is actually part of that semaphore group.

@ -1,57 +0,0 @@
pragma circom 2.1.2;
include "./eff_ecdsa.circom";
include "./tree.circom";
include "./to_address/zk-identity/eth.circom";
/**
* AddrMembership
* ==============
*
* Checks that an inputted efficient ECDSA signature (definition and discussion
* can be found at https://personaelabs.org/posts/efficient-ecdsa-1/)
* is signed by a public key that when converted to an address is a member of
* a Merkle tree of addresses. The public key is extracted from the efficient
* ECDSA signature in EfficientECDSA(), and converted to an address by Keccak
* hashing the public key in PubkeyToAddress().
*/
template AddrMembership(nLevels) {
signal input s;
signal input root;
signal input Tx;
signal input Ty;
signal input Ux;
signal input Uy;
signal input pathIndices[nLevels];
signal input siblings[nLevels];
component effEcdsa = EfficientECDSA();
effEcdsa.Tx <== Tx;
effEcdsa.Ty <== Ty;
effEcdsa.Ux <== Ux;
effEcdsa.Uy <== Uy;
effEcdsa.s <== s;
component pubKeyXBits = Num2Bits(256);
pubKeyXBits.in <== effEcdsa.pubKeyX;
component pubKeyYBits = Num2Bits(256);
pubKeyYBits.in <== effEcdsa.pubKeyY;
component pubToAddr = PubkeyToAddress();
for (var i = 0; i < 256; i++) {
pubToAddr.pubkeyBits[i] <== pubKeyYBits.out[i];
pubToAddr.pubkeyBits[i + 256] <== pubKeyXBits.out[i];
}
component merkleProof = MerkleTreeInclusionProof(nLevels);
merkleProof.leaf <== pubToAddr.address;
for (var i = 0; i < nLevels; i++) {
merkleProof.pathIndices[i] <== pathIndices[i];
merkleProof.siblings[i] <== siblings[i];
}
root === merkleProof.root;
}

@ -1,39 +0,0 @@
pragma circom 2.1.2;
include "./secp256k1/mul.circom";
include "circomlib/circuits/bitify.circom";
/**
* EfficientECDSA
* ====================
*
* Converts inputted efficient ECDSA signature to an public key. There is no
* public key validation included.
*/
template EfficientECDSA() {
var bits = 256;
signal input s;
signal input Tx; // T = r^-1 * R
signal input Ty;
signal input Ux; // U = -(m * r^-1 * G)
signal input Uy;
signal output pubKeyX;
signal output pubKeyY;
// sMultT = s * T
component sMultT = Secp256k1Mul();
sMultT.scalar <== s;
sMultT.xP <== Tx;
sMultT.yP <== Ty;
// pubKey = sMultT + U
component pubKey = Secp256k1AddComplete();
pubKey.xP <== sMultT.outX;
pubKey.yP <== sMultT.outY;
pubKey.xQ <== Ux;
pubKey.yQ <== Uy;
pubKeyX <== pubKey.outX;
pubKeyY <== pubKey.outY;
}

@ -1,42 +0,0 @@
pragma circom 2.1.2;
include "./eff_ecdsa.circom";
include "./to_address/zk-identity/eth.circom";
/**
* EfficientECDSAToAddr
* ====================
*
* Converts inputted efficient ECDSA signature to an address.
*/
template EfficientECDSAToAddr() {
var bits = 256;
signal input s;
signal input Tx; // T = r^-1 * R
signal input Ty;
signal input Ux; // U = -(m * r^-1 * G)
signal input Uy;
signal output addr;
component effEcdsa = EfficientECDSA();
effEcdsa.s <== s;
effEcdsa.Tx <== Tx;
effEcdsa.Ty <== Ty;
effEcdsa.Ux <== Ux;
effEcdsa.Uy <== Uy;
component pubKeyXBits = Num2Bits(256);
pubKeyXBits.in <== effEcdsa.pubKeyX;
component pubKeyYBits = Num2Bits(256);
pubKeyYBits.in <== effEcdsa.pubKeyY;
component pubToAddr = PubkeyToAddress();
for (var i = 0; i < 256; i++) {
pubToAddr.pubkeyBits[i] <== pubKeyYBits.out[i];
pubToAddr.pubkeyBits[i + 256] <== pubKeyXBits.out[i];
}
addr <== pubToAddr.address;
}

@ -1,46 +0,0 @@
pragma circom 2.1.2;
include "./eff_ecdsa.circom";
include "./tree.circom";
include "../poseidon/poseidon.circom";
/**
* PubkeyMembership
* ================
*
* Checks that an inputted efficient ECDSA signature (definition and discussion
* can be found at https://personaelabs.org/posts/efficient-ecdsa-1/)
* is signed by a public key that is in a Merkle tree of public keys. Avoids the
* SNARK-unfriendly Keccak hash that must be performed when validating if the
* public key is in a Merkle tree of addresses.
*/
template PubKeyMembership(nLevels) {
signal input s;
signal input root;
signal input Tx;
signal input Ty;
signal input Ux;
signal input Uy;
signal input pathIndices[nLevels];
signal input siblings[nLevels];
component ecdsa = EfficientECDSA();
ecdsa.Tx <== Tx;
ecdsa.Ty <== Ty;
ecdsa.Ux <== Ux;
ecdsa.Uy <== Uy;
ecdsa.s <== s;
component pubKeyHash = Poseidon();
pubKeyHash.inputs[0] <== ecdsa.pubKeyX;
pubKeyHash.inputs[1] <== ecdsa.pubKeyY;
component merkleProof = MerkleTreeInclusionProof(nLevels);
merkleProof.leaf <== pubKeyHash.out;
for (var i = 0; i < nLevels; i++) {
merkleProof.pathIndices[i] <== pathIndices[i];
merkleProof.siblings[i] <== siblings[i];
}
root === merkleProof.root;
}

@ -1,125 +0,0 @@
pragma circom 2.1.2;
include "circomlib/circuits/comparators.circom";
include "circomlib/circuits/gates.circom";
/**
* Secp256k1AddIncomplete
* ======================
*
* Adds two points (xP, yP) and (xQ, yQ) on the secp256k1 curve. This function
* only works for points where xP != xQ and are not at infinity. We can implement
* the raw formulae for this operation as we are doing right field arithmetic
* (we are doing secp256k1 base field arithmetic in the secq256k1 scalar field,
* which are equal). Should work for any short Weierstrass curve (Pasta, P-256).
*/
template Secp256k1AddIncomplete() {
signal input xP;
signal input yP;
signal input xQ;
signal input yQ;
signal output outX;
signal output outY;
signal lambda;
signal dx;
signal dy;
dx <== xP - xQ;
dy <== yP - yQ;
lambda <-- dy / dx;
dx * lambda === dy;
outX <== lambda * lambda - xP - xQ;
outY <== lambda * (xP - outX) - yP;
}
/**
* Secp256k1AddComplete
* ====================
*
* Implements https://zcash.github.io/halo2/design/gadgets/ecc/addition.html#complete-addition
* so we can add any pair of points. Assumes (0, 0) is not a valid point (which
* is true for secp256k1) and is used as the point at infinity.
*/
template Secp256k1AddComplete() {
signal input xP;
signal input yP;
signal input xQ;
signal input yQ;
signal output outX;
signal output outY;
signal xPSquared <== xP * xP;
component isXEqual = IsEqual();
isXEqual.in[0] <== xP;
isXEqual.in[1] <== xQ;
component isXpZero = IsZero();
isXpZero.in <== xP;
component isXqZero = IsZero();
isXqZero.in <== xQ;
component isXEitherZero = IsZero();
isXEitherZero.in <== (1 - isXpZero.out) * (1 - isXqZero.out);
// dx = xQ - xP
// dy = xP != xQ ? yQ - yP : 0
// lambdaA = xP != xQ ? (yQ - yP) / (xQ - xP) : 0
signal dx <== xQ - xP;
signal dy <== (yQ - yP) * (1 - isXEqual.out);
signal lambdaA <-- ((yQ - yP) / dx) * (1 - isXEqual.out);
dx * lambdaA === dy;
// lambdaB = (3 * xP^2) / (2 * yP)
signal lambdaB <-- ((3 * xPSquared) / (2 * yP));
lambdaB * 2 * yP === 3 * xPSquared;
// lambda = xP != xQ ? lambdaA : lambdaB
signal lambda <== (lambdaB * isXEqual.out) + lambdaA;
// outAx = lambda^2 - xP - xQ
// outAy = lambda * (xP - outAx) - yP
signal outAx <== lambda * lambda - xP - xQ;
signal outAy <== lambda * (xP - outAx) - yP;
// (outBx, outBy) = xP != 0 and xQ != 0 ? (outAx, outAy) : (0, 0)
signal outBx <== outAx * (1 - isXEitherZero.out);
signal outBy <== outAy * (1 - isXEitherZero.out);
//(outCx, outCy) = xP = 0 ? (xQ, yQ) : (0, 0)
signal outCx <== isXpZero.out * xQ;
signal outCy <== isXpZero.out * yQ;
// (outDx, outDy) = xQ = 0 ? (xP, yP) : (0, 0)
signal outDx <== isXqZero.out * xP;
signal outDy <== isXqZero.out * yP;
// zeroizeA = (xP = xQ and yP = -yQ) ? 1 : 0
component zeroizeA = IsEqual();
zeroizeA.in[0] <== isXEqual.out;
zeroizeA.in[1] <== 1 - (yP + yQ);
// zeroizeB = (xP = 0 and xQ = 0) ? 1 : 0
component zeroizeB = AND();
zeroizeB.a <== isXpZero.out;
zeroizeB.b <== isXqZero.out;
// zeroize = (xP = xQ and yP = -yQ) or (xP = 0 and xQ = 0) ? 1 : 0
// for this case we want to output the point at infinity (0, 0)
component zeroize = OR();
zeroize.a <== zeroizeA.out;
zeroize.b <== zeroizeB.out;
// The below three conditionals are mutually exclusive when zeroize = 0,
// so we can safely sum the outputs.
// outBx != 0 iff xP != 0 and xQ != 0
// outCx != 0 iff xP = 0
// outDx != 0 iff xQ = 0
outX <== (outBx + outCx + outDx) * (1 - zeroize.out);
outY <== (outBy + outCy + outDy) * (1 - zeroize.out);
}

@ -1,27 +0,0 @@
pragma circom 2.1.2;
/**
* Secp256k1Double
* ===============
*
* Double a specific point (xP, yP) on the secp256k1 curve. Should work for any
* short Weierstrass curve (Pasta, P-256).
*/
template Secp256k1Double() {
signal input xP;
signal input yP;
signal output outX;
signal output outY;
signal lambda;
signal xPSquared;
xPSquared <== xP * xP;
lambda <-- (3 * xPSquared) / (2 * yP);
lambda * 2 * yP === 3 * xPSquared;
outX <== lambda * lambda - (2 * xP);
outY <== lambda * (xP - outX) - yP;
}

@ -1,190 +0,0 @@
pragma circom 2.1.2;
include "./add.circom";
include "./double.circom";
include "circomlib/circuits/bitify.circom";
include "circomlib/circuits/comparators.circom";
include "circomlib/circuits/gates.circom";
//
/**
* Secp256k1Mul
* ============
*
* Implements https://zcash.github.io/halo2/design/gadgets/ecc/var-base-scalar-mul.html
* which allows us to use incomplete addition for the majority of the addition steps
* and only use complete addition for the final 3 steps.
*/
template Secp256k1Mul() {
var bits = 256;
signal input scalar;
signal input xP;
signal input yP;
signal output outX;
signal output outY;
component kBits = K();
kBits.s <== scalar;
component acc0 = Secp256k1Double();
acc0.xP <== xP;
acc0.yP <== yP;
component PIncomplete[bits-3];
component accIncomplete[bits];
for (var i = 0; i < bits-3; i++) {
if (i == 0) {
PIncomplete[i] = Secp256k1AddIncomplete(); // (Acc + P)
PIncomplete[i].xP <== xP; // kBits[i] ? xP : -xP;
PIncomplete[i].yP <== -yP;// kBits[i] ? xP : -xP;
PIncomplete[i].xQ <== acc0.outX;
PIncomplete[i].yQ <== acc0.outY;
accIncomplete[i] = Secp256k1AddIncomplete(); // (Acc + P) + Acc
accIncomplete[i].xP <== acc0.outX;
accIncomplete[i].yP <== acc0.outY;
accIncomplete[i].xQ <== PIncomplete[i].outX;
accIncomplete[i].yQ <== PIncomplete[i].outY;
} else {
PIncomplete[i] = Secp256k1AddIncomplete(); // (Acc + P)
PIncomplete[i].xP <== xP; // k_i ? xP : -xP;
PIncomplete[i].yP <== (2 * kBits.out[bits-i] - 1) * yP;// k_i ? xP : -xP;
PIncomplete[i].xQ <== accIncomplete[i-1].outX;
PIncomplete[i].yQ <== accIncomplete[i-1].outY;
accIncomplete[i] = Secp256k1AddIncomplete(); // (Acc + P) + Acc
accIncomplete[i].xP <== accIncomplete[i-1].outX;
accIncomplete[i].yP <== accIncomplete[i-1].outY;
accIncomplete[i].xQ <== PIncomplete[i].outX;
accIncomplete[i].yQ <== PIncomplete[i].outY;
}
}
component PComplete[bits-3];
component accComplete[3];
for (var i = 0; i < 3; i++) {
PComplete[i] = Secp256k1AddComplete(); // (Acc + P)
PComplete[i].xP <== xP; // k_i ? xP : -xP;
PComplete[i].yP <== (2 * kBits.out[3 - i] - 1) * yP;// k_i ? xP : -xP;
if (i == 0) {
PComplete[i].xQ <== accIncomplete[252].outX;
PComplete[i].yQ <== accIncomplete[252].outY;
} else {
PComplete[i].xQ <== accComplete[i-1].outX;
PComplete[i].yQ <== accComplete[i-1].outY;
}
accComplete[i] = Secp256k1AddComplete(); // (Acc + P) + Acc
if (i == 0) {
accComplete[i].xP <== accIncomplete[252].outX;
accComplete[i].yP <== accIncomplete[252].outY;
} else {
accComplete[i].xP <== accComplete[i-1].outX;
accComplete[i].yP <== accComplete[i-1].outY;
}
accComplete[i].xQ <== PComplete[i].outX;
accComplete[i].yQ <== PComplete[i].outY;
}
component out = Secp256k1AddComplete();
out.xP <== accComplete[2].outX;
out.yP <== accComplete[2].outY;
out.xQ <== (1 - kBits.out[0]) * xP;
out.yQ <== (1 - kBits.out[0]) * -yP;
outX <== out.outX;
outY <== out.outY;
}
// Calculate k = (s + tQ) % q as follows:
// Define notation: (s + tQ) / q = (quotient, remainder)
// We can calculate the quotient and remainder as:
// (s + tQ) < q ? = (0, s - tQ) : (1, (s - tQ) - q)
// We use 128-bit registers to calculate the above since (s + tQ) can be larger than p.
template K() {
var bits = 256;
signal input s;
signal output out[bits];
// Split elemnts into 128 bit registers
var q = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141; // The order of the scalar field
var qlo = q & ((2 ** 128) - 1);
var qhi = q >> 128;
var tQ = 115792089237316195423570985008687907852405143892509244725752742275123193348738; // (q - 2^256) % q;
var tQlo = tQ & (2 ** (128) - 1);
var tQhi = tQ >> 128;
signal slo <-- s & (2 ** (128) - 1);
signal shi <-- s >> 128;
// Get carry bit of (slo + tQlo)
component inBits = Num2Bits(128 + 1);
inBits.in <== slo + tQlo;
signal carry <== inBits.out[128];
// check a >= b
// where
// a = (s + tQ)
// b = q
// - alpha: ahi > bhi
// - beta: ahi = bhi
// - gamma: alo ≥ blo
// if alpha or (beta and gamma) then a >= b
signal ahi <== shi + tQhi + carry;
signal bhi <== qhi;
signal alo <== slo + tQlo - (carry * 2 ** 128);
signal blo <== qlo;
component alpha = GreaterThan(129);
alpha.in[0] <== ahi;
alpha.in[1] <== bhi;
component beta = IsEqual();
beta.in[0] <== ahi;
beta.in[1] <== bhi;
component gamma = GreaterEqThan(129);
gamma.in[0] <== alo;
gamma.in[1] <== blo;
component betaANDgamma = AND();
betaANDgamma.a <== beta.out;
betaANDgamma.b <== gamma.out;
component isQuotientOne = OR();
isQuotientOne.a <== betaANDgamma.out;
isQuotientOne.b <== alpha.out;
// theta: (slo + tQlo) < qlo
component theta = GreaterThan(129);
theta.in[0] <== qlo;
theta.in[1] <== slo + tQlo;
// borrow: (slo + tQlo) < qlo and isQuotientOne ? 1 : 0
component borrow = AND();
borrow.a <== theta.out;
borrow.b <== isQuotientOne.out;
signal klo <== (slo + tQlo + borrow.out * (2 ** 128)) - isQuotientOne.out * qlo;
signal khi <== (shi + tQhi - borrow.out * 1) - isQuotientOne.out * qhi;
component kloBits = Num2Bits(256);
kloBits.in <== klo;
component khiBits = Num2Bits(256);
khiBits.in <== khi;
for (var i = 0; i < 128; i++) {
out[i] <== kloBits.out[i];
out[i + 128] <== khiBits.out[i];
}
}

@ -1,183 +0,0 @@
pragma circom 2.0.2;
include "./utils.circom";
include "./permutations.circom";
template Pad(nBits) {
signal input in[nBits];
var blockSize=136*8;
signal output out[blockSize];
signal out2[blockSize];
var i;
for (i=0; i<nBits; i++) {
out2[i] <== in[i];
}
var domain = 0x01;
for (i=0; i<8; i++) {
out2[nBits+i] <== (domain >> i) & 1;
}
for (i=nBits+8; i<blockSize; i++) {
out2[i] <== 0;
}
component aux = OrArray(8);
for (i=0; i<8; i++) {
aux.a[i] <== out2[blockSize-8+i];
aux.b[i] <== (0x80 >> i) & 1;
}
for (i=0; i<8; i++) {
out[blockSize-8+i] <== aux.out[i];
}
for (i=0; i<blockSize-8; i++) {
out[i]<==out2[i];
}
}
template KeccakfRound(r) {
signal input in[25*64];
signal output out[25*64];
var i;
component theta = Theta();
component rhopi = RhoPi();
component chi = Chi();
component iota = Iota(r);
for (i=0; i<25*64; i++) {
theta.in[i] <== in[i];
}
for (i=0; i<25*64; i++) {
rhopi.in[i] <== theta.out[i];
}
for (i=0; i<25*64; i++) {
chi.in[i] <== rhopi.out[i];
}
for (i=0; i<25*64; i++) {
iota.in[i] <== chi.out[i];
}
for (i=0; i<25*64; i++) {
out[i] <== iota.out[i];
}
}
template Absorb() {
var blockSizeBytes=136;
signal input s[25*64];
signal input block[blockSizeBytes*8];
signal output out[25*64];
var i;
var j;
component aux[blockSizeBytes/8];
component newS = Keccakf();
for (i=0; i<blockSizeBytes/8; i++) {
aux[i] = XorArray(64);
for (j=0; j<64; j++) {
aux[i].a[j] <== s[i*64+j];
aux[i].b[j] <== block[i*64+j];
}
for (j=0; j<64; j++) {
newS.in[i*64+j] <== aux[i].out[j];
}
}
// fill the missing s that was not covered by the loop over
// blockSizeBytes/8
for (i=(blockSizeBytes/8)*64; i<25*64; i++) {
newS.in[i] <== s[i];
}
for (i=0; i<25*64; i++) {
out[i] <== newS.out[i];
}
}
template Final(nBits) {
signal input in[nBits];
signal output out[25*64];
var blockSize=136*8;
var i;
// pad
component pad = Pad(nBits);
for (i=0; i<nBits; i++) {
pad.in[i] <== in[i];
}
// absorb
component abs = Absorb();
for (i=0; i<blockSize; i++) {
abs.block[i] <== pad.out[i];
}
for (i=0; i<25*64; i++) {
abs.s[i] <== 0;
}
for (i=0; i<25*64; i++) {
out[i] <== abs.out[i];
}
}
template Squeeze(nBits) {
signal input s[25*64];
signal output out[nBits];
var i;
var j;
for (i=0; i<25; i++) {
for (j=0; j<64; j++) {
if (i*64+j<nBits) {
out[i*64+j] <== s[i*64+j];
}
}
}
}
template Keccakf() {
signal input in[25*64];
signal output out[25*64];
var i;
var j;
// 24 rounds
component round[24];
signal midRound[24*25*64];
for (i=0; i<24; i++) {
round[i] = KeccakfRound(i);
if (i==0) {
for (j=0; j<25*64; j++) {
midRound[j] <== in[j];
}
}
for (j=0; j<25*64; j++) {
round[i].in[j] <== midRound[i*25*64+j];
}
if (i<23) {
for (j=0; j<25*64; j++) {
midRound[(i+1)*25*64+j] <== round[i].out[j];
}
}
}
for (i=0; i<25*64; i++) {
out[i] <== round[23].out[i];
}
}
template Keccak(nBitsIn, nBitsOut) {
signal input in[nBitsIn];
signal output out[nBitsOut];
var i;
component f = Final(nBitsIn);
for (i=0; i<nBitsIn; i++) {
f.in[i] <== in[i];
}
component squeeze = Squeeze(nBitsOut);
for (i=0; i<25*64; i++) {
squeeze.s[i] <== f.out[i];
}
for (i=0; i<nBitsOut; i++) {
out[i] <== squeeze.out[i];
}
}

@ -1,796 +0,0 @@
pragma circom 2.0.2;
include "./utils.circom";
// Theta
template D(n, shl, shr) {
// d = b ^ (a<<shl | a>>shr)
signal input a[n];
signal input b[n];
signal output out[n];
var i;
component aux0 = ShR(64, shr);
for (i=0; i<64; i++) {
aux0.in[i] <== a[i];
}
component aux1 = ShL(64, shl);
for (i=0; i<64; i++) {
aux1.in[i] <== a[i];
}
component aux2 = OrArray(64);
for (i=0; i<64; i++) {
aux2.a[i] <== aux0.out[i];
aux2.b[i] <== aux1.out[i];
}
component aux3 = XorArray(64);
for (i=0; i<64; i++) {
aux3.a[i] <== b[i];
aux3.b[i] <== aux2.out[i];
}
for (i=0; i<64; i++) {
out[i] <== aux3.out[i];
}
}
template Theta() {
signal input in[25*64];
signal output out[25*64];
var i;
component c0 = Xor5(64);
for (i=0; i<64; i++) {
c0.a[i] <== in[i];
c0.b[i] <== in[5*64+i];
c0.c[i] <== in[10*64+i];
c0.d[i] <== in[15*64+i];
c0.e[i] <== in[20*64+i];
}
component c1 = Xor5(64);
for (i=0; i<64; i++) {
c1.a[i] <== in[1*64+i];
c1.b[i] <== in[6*64+i];
c1.c[i] <== in[11*64+i];
c1.d[i] <== in[16*64+i];
c1.e[i] <== in[21*64+i];
}
component c2 = Xor5(64);
for (i=0; i<64; i++) {
c2.a[i] <== in[2*64+i];
c2.b[i] <== in[7*64+i];
c2.c[i] <== in[12*64+i];
c2.d[i] <== in[17*64+i];
c2.e[i] <== in[22*64+i];
}
component c3 = Xor5(64);
for (i=0; i<64; i++) {
c3.a[i] <== in[3*64+i];
c3.b[i] <== in[8*64+i];
c3.c[i] <== in[13*64+i];
c3.d[i] <== in[18*64+i];
c3.e[i] <== in[23*64+i];
}
component c4 = Xor5(64);
for (i=0; i<64; i++) {
c4.a[i] <== in[4*64+i];
c4.b[i] <== in[9*64+i];
c4.c[i] <== in[14*64+i];
c4.d[i] <== in[19*64+i];
c4.e[i] <== in[24*64+i];
}
// d = c4 ^ (c1<<1 | c1>>(64-1))
component d0 = D(64, 1, 64-1);
for (i=0; i<64; i++) {
d0.a[i] <== c1.out[i];
d0.b[i] <== c4.out[i];
}
// r[0] = a[0] ^ d
component r0 = XorArray(64);
for (i=0; i<64; i++) {
r0.a[i] <== in[i];
r0.b[i] <== d0.out[i];
}
for (i=0; i<64; i++) {
out[i] <== r0.out[i];
}
// r[5] = a[5] ^ d
component r5 = XorArray(64);
for (i=0; i<64; i++) {
r5.a[i] <== in[5*64+i];
r5.b[i] <== d0.out[i];
}
for (i=0; i<64; i++) {
out[5*64+i] <== r5.out[i];
}
// r[10] = a[10] ^ d
component r10 = XorArray(64);
for (i=0; i<64; i++) {
r10.a[i] <== in[10*64+i];
r10.b[i] <== d0.out[i];
}
for (i=0; i<64; i++) {
out[10*64+i] <== r10.out[i];
}
// r[15] = a[15] ^ d
component r15 = XorArray(64);
for (i=0; i<64; i++) {
r15.a[i] <== in[15*64+i];
r15.b[i] <== d0.out[i];
}
for (i=0; i<64; i++) {
out[15*64+i] <== r15.out[i];
}
// r[20] = a[20] ^ d
component r20 = XorArray(64);
for (i=0; i<64; i++) {
r20.a[i] <== in[20*64+i];
r20.b[i] <== d0.out[i];
}
for (i=0; i<64; i++) {
out[20*64+i] <== r20.out[i];
}
// d = c0 ^ (c2<<1 | c2>>(64-1))
component d1 = D(64, 1, 64-1);
for (i=0; i<64; i++) {
d1.a[i] <== c2.out[i];
d1.b[i] <== c0.out[i];
}
// r[1] = a[1] ^ d
component r1 = XorArray(64);
for (i=0; i<64; i++) {
r1.a[i] <== in[1*64+i];
r1.b[i] <== d1.out[i];
}
for (i=0; i<64; i++) {
out[1*64+i] <== r1.out[i];
}
// r[6] = a[6] ^ d
component r6 = XorArray(64);
for (i=0; i<64; i++) {
r6.a[i] <== in[6*64+i];
r6.b[i] <== d1.out[i];
}
for (i=0; i<64; i++) {
out[6*64+i] <== r6.out[i];
}
// r[11] = a[11] ^ d
component r11 = XorArray(64);
for (i=0; i<64; i++) {
r11.a[i] <== in[11*64+i];
r11.b[i] <== d1.out[i];
}
for (i=0; i<64; i++) {
out[11*64+i] <== r11.out[i];
}
// r[16] = a[16] ^ d
component r16 = XorArray(64);
for (i=0; i<64; i++) {
r16.a[i] <== in[16*64+i];
r16.b[i] <== d1.out[i];
}
for (i=0; i<64; i++) {
out[16*64+i] <== r16.out[i];
}
// r[21] = a[21] ^ d
component r21 = XorArray(64);
for (i=0; i<64; i++) {
r21.a[i] <== in[21*64+i];
r21.b[i] <== d1.out[i];
}
for (i=0; i<64; i++) {
out[21*64+i] <== r21.out[i];
}
// d = c1 ^ (c3<<1 | c3>>(64-1))
component d2 = D(64, 1, 64-1);
for (i=0; i<64; i++) {
d2.a[i] <== c3.out[i];
d2.b[i] <== c1.out[i];
}
// r[2] = a[2] ^ d
component r2 = XorArray(64);
for (i=0; i<64; i++) {
r2.a[i] <== in[2*64+i];
r2.b[i] <== d2.out[i];
}
for (i=0; i<64; i++) {
out[2*64+i] <== r2.out[i];
}
// r[7] = a[7] ^ d
component r7 = XorArray(64);
for (i=0; i<64; i++) {
r7.a[i] <== in[7*64+i];
r7.b[i] <== d2.out[i];
}
for (i=0; i<64; i++) {
out[7*64+i] <== r7.out[i];
}
// r[12] = a[12] ^ d
component r12 = XorArray(64);
for (i=0; i<64; i++) {
r12.a[i] <== in[12*64+i];
r12.b[i] <== d2.out[i];
}
for (i=0; i<64; i++) {
out[12*64+i] <== r12.out[i];
}
// r[17] = a[17] ^ d
component r17 = XorArray(64);
for (i=0; i<64; i++) {
r17.a[i] <== in[17*64+i];
r17.b[i] <== d2.out[i];
}
for (i=0; i<64; i++) {
out[17*64+i] <== r17.out[i];
}
// r[22] = a[22] ^ d
component r22 = XorArray(64);
for (i=0; i<64; i++) {
r22.a[i] <== in[22*64+i];
r22.b[i] <== d2.out[i];
}
for (i=0; i<64; i++) {
out[22*64+i] <== r22.out[i];
}
// d = c2 ^ (c4<<1 | c4>>(64-1))
component d3 = D(64, 1, 64-1);
for (i=0; i<64; i++) {
d3.a[i] <== c4.out[i];
d3.b[i] <== c2.out[i];
}
// r[3] = a[3] ^ d
component r3 = XorArray(64);
for (i=0; i<64; i++) {
r3.a[i] <== in[3*64+i];
r3.b[i] <== d3.out[i];
}
for (i=0; i<64; i++) {
out[3*64+i] <== r3.out[i];
}
// r[8] = a[8] ^ d
component r8 = XorArray(64);
for (i=0; i<64; i++) {
r8.a[i] <== in[8*64+i];
r8.b[i] <== d3.out[i];
}
for (i=0; i<64; i++) {
out[8*64+i] <== r8.out[i];
}
// r[13] = a[13] ^ d
component r13 = XorArray(64);
for (i=0; i<64; i++) {
r13.a[i] <== in[13*64+i];
r13.b[i] <== d3.out[i];
}
for (i=0; i<64; i++) {
out[13*64+i] <== r13.out[i];
}
// r[18] = a[18] ^ d
component r18 = XorArray(64);
for (i=0; i<64; i++) {
r18.a[i] <== in[18*64+i];
r18.b[i] <== d3.out[i];
}
for (i=0; i<64; i++) {
out[18*64+i] <== r18.out[i];
}
// r[23] = a[23] ^ d
component r23 = XorArray(64);
for (i=0; i<64; i++) {
r23.a[i] <== in[23*64+i];
r23.b[i] <== d3.out[i];
}
for (i=0; i<64; i++) {
out[23*64+i] <== r23.out[i];
}
// d = c3 ^ (c0<<1 | c0>>(64-1))
component d4 = D(64, 1, 64-1);
for (i=0; i<64; i++) {
d4.a[i] <== c0.out[i];
d4.b[i] <== c3.out[i];
}
// r[4] = a[4] ^ d
component r4 = XorArray(64);
for (i=0; i<64; i++) {
r4.a[i] <== in[4*64+i];
r4.b[i] <== d4.out[i];
}
for (i=0; i<64; i++) {
out[4*64+i] <== r4.out[i];
}
// r[9] = a[9] ^ d
component r9 = XorArray(64);
for (i=0; i<64; i++) {
r9.a[i] <== in[9*64+i];
r9.b[i] <== d4.out[i];
}
for (i=0; i<64; i++) {
out[9*64+i] <== r9.out[i];
}
// r[14] = a[14] ^ d
component r14 = XorArray(64);
for (i=0; i<64; i++) {
r14.a[i] <== in[14*64+i];
r14.b[i] <== d4.out[i];
}
for (i=0; i<64; i++) {
out[14*64+i] <== r14.out[i];
}
// r[19] = a[19] ^ d
component r19 = XorArray(64);
for (i=0; i<64; i++) {
r19.a[i] <== in[19*64+i];
r19.b[i] <== d4.out[i];
}
for (i=0; i<64; i++) {
out[19*64+i] <== r19.out[i];
}
// r[24] = a[24] ^ d
component r24 = XorArray(64);
for (i=0; i<64; i++) {
r24.a[i] <== in[24*64+i];
r24.b[i] <== d4.out[i];
}
for (i=0; i<64; i++) {
out[24*64+i] <== r24.out[i];
}
}
// RhoPi
template stepRhoPi(shl, shr) {
// out = a<<shl|a>>shr
signal input a[64];
signal output out[64];
var i;
component aux0 = ShR(64, shr);
for (i=0; i<64; i++) {
aux0.in[i] <== a[i];
}
component aux1 = ShL(64, shl);
for (i=0; i<64; i++) {
aux1.in[i] <== a[i];
}
component aux2 = OrArray(64);
for (i=0; i<64; i++) {
aux2.a[i] <== aux0.out[i];
aux2.b[i] <== aux1.out[i];
}
for (i=0; i<64; i++) {
out[i] <== aux2.out[i];
}
}
template RhoPi() {
signal input in[25*64];
signal output out[25*64];
var i;
// r[10] = a[1]<<1|a[1]>>(64-1)
component s10 = stepRhoPi(1, 64-1);
for (i=0; i<64; i++) {
s10.a[i] <== in[1*64+i];
}
// r[7] = a[10]<<3|a[10]>>(64-3)
component s7 = stepRhoPi(3, 64-3);
for (i=0; i<64; i++) {
s7.a[i] <== in[10*64+i];
}
// r[11] = a[7]<<6|a[7]>>(64-6)
component s11 = stepRhoPi(6, 64-6);
for (i=0; i<64; i++) {
s11.a[i] <== in[7*64+i];
}
// r[17] = a[11]<<10|a[11]>>(64-10)
component s17 = stepRhoPi(10, 64-10);
for (i=0; i<64; i++) {
s17.a[i] <== in[11*64+i];
}
// r[18] = a[17]<<15|a[17]>>(64-15)
component s18 = stepRhoPi(15, 64-15);
for (i=0; i<64; i++) {
s18.a[i] <== in[17*64+i];
}
// r[3] = a[18]<<21|a[18]>>(64-21)
component s3 = stepRhoPi(21, 64-21);
for (i=0; i<64; i++) {
s3.a[i] <== in[18*64+i];
}
// r[5] = a[3]<<28|a[3]>>(64-28)
component s5 = stepRhoPi(28, 64-28);
for (i=0; i<64; i++) {
s5.a[i] <== in[3*64+i];
}
// r[16] = a[5]<<36|a[5]>>(64-36)
component s16 = stepRhoPi(36, 64-36);
for (i=0; i<64; i++) {
s16.a[i] <== in[5*64+i];
}
// r[8] = a[16]<<45|a[16]>>(64-45)
component s8 = stepRhoPi(45, 64-45);
for (i=0; i<64; i++) {
s8.a[i] <== in[16*64+i];
}
// r[21] = a[8]<<55|a[8]>>(64-55)
component s21 = stepRhoPi(55, 64-55);
for (i=0; i<64; i++) {
s21.a[i] <== in[8*64+i];
}
// r[24] = a[21]<<2|a[21]>>(64-2)
component s24 = stepRhoPi(2, 64-2);
for (i=0; i<64; i++) {
s24.a[i] <== in[21*64+i];
}
// r[4] = a[24]<<14|a[24]>>(64-14)
component s4 = stepRhoPi(14, 64-14);
for (i=0; i<64; i++) {
s4.a[i] <== in[24*64+i];
}
// r[15] = a[4]<<27|a[4]>>(64-27)
component s15 = stepRhoPi(27, 64-27);
for (i=0; i<64; i++) {
s15.a[i] <== in[4*64+i];
}
// r[23] = a[15]<<41|a[15]>>(64-41)
component s23 = stepRhoPi(41, 64-41);
for (i=0; i<64; i++) {
s23.a[i] <== in[15*64+i];
}
// r[19] = a[23]<<56|a[23]>>(64-56)
component s19 = stepRhoPi(56, 64-56);
for (i=0; i<64; i++) {
s19.a[i] <== in[23*64+i];
}
// r[13] = a[19]<<8|a[19]>>(64-8)
component s13 = stepRhoPi(8, 64-8);
for (i=0; i<64; i++) {
s13.a[i] <== in[19*64+i];
}
// r[12] = a[13]<<25|a[13]>>(64-25)
component s12 = stepRhoPi(25, 64-25);
for (i=0; i<64; i++) {
s12.a[i] <== in[13*64+i];
}
// r[2] = a[12]<<43|a[12]>>(64-43)
component s2 = stepRhoPi(43, 64-43);
for (i=0; i<64; i++) {
s2.a[i] <== in[12*64+i];
}
// r[20] = a[2]<<62|a[2]>>(64-62)
component s20 = stepRhoPi(62, 64-62);
for (i=0; i<64; i++) {
s20.a[i] <== in[2*64+i];
}
// r[14] = a[20]<<18|a[20]>>(64-18)
component s14 = stepRhoPi(18, 64-18);
for (i=0; i<64; i++) {
s14.a[i] <== in[20*64+i];
}
// r[22] = a[14]<<39|a[14]>>(64-39)
component s22 = stepRhoPi(39, 64-39);
for (i=0; i<64; i++) {
s22.a[i] <== in[14*64+i];
}
// r[9] = a[22]<<61|a[22]>>(64-61)
component s9 = stepRhoPi(61, 64-61);
for (i=0; i<64; i++) {
s9.a[i] <== in[22*64+i];
}
// r[6] = a[9]<<20|a[9]>>(64-20)
component s6 = stepRhoPi(20, 64-20);
for (i=0; i<64; i++) {
s6.a[i] <== in[9*64+i];
}
// r[1] = a[6]<<44|a[6]>>(64-44)
component s1 = stepRhoPi(44, 64-44);
for (i=0; i<64; i++) {
s1.a[i] <== in[6*64+i];
}
for (i=0; i<64; i++) {
out[i] <== in[i];
out[10*64+i] <== s10.out[i];
out[7*64+i] <== s7.out[i];
out[11*64+i] <== s11.out[i];
out[17*64+i] <== s17.out[i];
out[18*64+i] <== s18.out[i];
out[3*64+i] <== s3.out[i];
out[5*64+i] <== s5.out[i];
out[16*64+i] <== s16.out[i];
out[8*64+i] <== s8.out[i];
out[21*64+i] <== s21.out[i];
out[24*64+i] <== s24.out[i];
out[4*64+i] <== s4.out[i];
out[15*64+i] <== s15.out[i];
out[23*64+i] <== s23.out[i];
out[19*64+i] <== s19.out[i];
out[13*64+i] <== s13.out[i];
out[12*64+i] <== s12.out[i];
out[2*64+i] <== s2.out[i];
out[20*64+i] <== s20.out[i];
out[14*64+i] <== s14.out[i];
out[22*64+i] <== s22.out[i];
out[9*64+i] <== s9.out[i];
out[6*64+i] <== s6.out[i];
out[1*64+i] <== s1.out[i];
}
}
// Chi
template stepChi() {
// out = a ^ (^b) & c
signal input a[64];
signal input b[64];
signal input c[64];
signal output out[64];
var i;
// ^b
component bXor = XorArraySingle(64);
for (i=0; i<64; i++) {
bXor.a[i] <== b[i];
}
// (^b)&c
component bc = AndArray(64);
for (i=0; i<64; i++) {
bc.a[i] <== bXor.out[i];
bc.b[i] <== c[i];
}
// a^(^b)&c
component abc = XorArray(64);
for (i=0; i<64; i++) {
abc.a[i] <== a[i];
abc.b[i] <== bc.out[i];
}
for (i=0; i<64; i++) {
out[i] <== abc.out[i];
}
}
template Chi() {
signal input in[25*64];
signal output out[25*64];
var i;
component r0 = stepChi();
for (i=0; i<64; i++) {
r0.a[i] <== in[i];
r0.b[i] <== in[1*64+i];
r0.c[i] <== in[2*64+i];
}
component r1 = stepChi();
for (i=0; i<64; i++) {
r1.a[i] <== in[1*64+i];
r1.b[i] <== in[2*64+i];
r1.c[i] <== in[3*64+i];
}
component r2 = stepChi();
for (i=0; i<64; i++) {
r2.a[i] <== in[2*64+i];
r2.b[i] <== in[3*64+i];
r2.c[i] <== in[4*64+i];
}
component r3 = stepChi();
for (i=0; i<64; i++) {
r3.a[i] <== in[3*64+i];
r3.b[i] <== in[4*64+i];
r3.c[i] <== in[0*64+i];
}
component r4 = stepChi();
for (i=0; i<64; i++) {
r4.a[i] <== in[4*64+i];
r4.b[i] <== in[i];
r4.c[i] <== in[1*64+i];
}
component r5 = stepChi();
for (i=0; i<64; i++) {
r5.a[i] <== in[5*64+i];
r5.b[i] <== in[6*64+i];
r5.c[i] <== in[7*64+i];
}
component r6 = stepChi();
for (i=0; i<64; i++) {
r6.a[i] <== in[6*64+i];
r6.b[i] <== in[7*64+i];
r6.c[i] <== in[8*64+i];
}
component r7 = stepChi();
for (i=0; i<64; i++) {
r7.a[i] <== in[7*64+i];
r7.b[i] <== in[8*64+i];
r7.c[i] <== in[9*64+i];
}
component r8 = stepChi();
for (i=0; i<64; i++) {
r8.a[i] <== in[8*64+i];
r8.b[i] <== in[9*64+i];
r8.c[i] <== in[5*64+i];
}
component r9 = stepChi();
for (i=0; i<64; i++) {
r9.a[i] <== in[9*64+i];
r9.b[i] <== in[5*64+i];
r9.c[i] <== in[6*64+i];
}
component r10 = stepChi();
for (i=0; i<64; i++) {
r10.a[i] <== in[10*64+i];
r10.b[i] <== in[11*64+i];
r10.c[i] <== in[12*64+i];
}
component r11 = stepChi();
for (i=0; i<64; i++) {
r11.a[i] <== in[11*64+i];
r11.b[i] <== in[12*64+i];
r11.c[i] <== in[13*64+i];
}
component r12 = stepChi();
for (i=0; i<64; i++) {
r12.a[i] <== in[12*64+i];
r12.b[i] <== in[13*64+i];
r12.c[i] <== in[14*64+i];
}
component r13 = stepChi();
for (i=0; i<64; i++) {
r13.a[i] <== in[13*64+i];
r13.b[i] <== in[14*64+i];
r13.c[i] <== in[10*64+i];
}
component r14 = stepChi();
for (i=0; i<64; i++) {
r14.a[i] <== in[14*64+i];
r14.b[i] <== in[10*64+i];
r14.c[i] <== in[11*64+i];
}
component r15 = stepChi();
for (i=0; i<64; i++) {
r15.a[i] <== in[15*64+i];
r15.b[i] <== in[16*64+i];
r15.c[i] <== in[17*64+i];
}
component r16 = stepChi();
for (i=0; i<64; i++) {
r16.a[i] <== in[16*64+i];
r16.b[i] <== in[17*64+i];
r16.c[i] <== in[18*64+i];
}
component r17 = stepChi();
for (i=0; i<64; i++) {
r17.a[i] <== in[17*64+i];
r17.b[i] <== in[18*64+i];
r17.c[i] <== in[19*64+i];
}
component r18 = stepChi();
for (i=0; i<64; i++) {
r18.a[i] <== in[18*64+i];
r18.b[i] <== in[19*64+i];
r18.c[i] <== in[15*64+i];
}
component r19 = stepChi();
for (i=0; i<64; i++) {
r19.a[i] <== in[19*64+i];
r19.b[i] <== in[15*64+i];
r19.c[i] <== in[16*64+i];
}
component r20 = stepChi();
for (i=0; i<64; i++) {
r20.a[i] <== in[20*64+i];
r20.b[i] <== in[21*64+i];
r20.c[i] <== in[22*64+i];
}
component r21 = stepChi();
for (i=0; i<64; i++) {
r21.a[i] <== in[21*64+i];
r21.b[i] <== in[22*64+i];
r21.c[i] <== in[23*64+i];
}
component r22 = stepChi();
for (i=0; i<64; i++) {
r22.a[i] <== in[22*64+i];
r22.b[i] <== in[23*64+i];
r22.c[i] <== in[24*64+i];
}
component r23 = stepChi();
for (i=0; i<64; i++) {
r23.a[i] <== in[23*64+i];
r23.b[i] <== in[24*64+i];
r23.c[i] <== in[20*64+i];
}
component r24 = stepChi();
for (i=0; i<64; i++) {
r24.a[i] <== in[24*64+i];
r24.b[i] <== in[20*64+i];
r24.c[i] <== in[21*64+i];
}
for (i=0; i<64; i++) {
out[i] <== r0.out[i];
out[1*64+i] <== r1.out[i];
out[2*64+i] <== r2.out[i];
out[3*64+i] <== r3.out[i];
out[4*64+i] <== r4.out[i];
out[5*64+i] <== r5.out[i];
out[6*64+i] <== r6.out[i];
out[7*64+i] <== r7.out[i];
out[8*64+i] <== r8.out[i];
out[9*64+i] <== r9.out[i];
out[10*64+i] <== r10.out[i];
out[11*64+i] <== r11.out[i];
out[12*64+i] <== r12.out[i];
out[13*64+i] <== r13.out[i];
out[14*64+i] <== r14.out[i];
out[15*64+i] <== r15.out[i];
out[16*64+i] <== r16.out[i];
out[17*64+i] <== r17.out[i];
out[18*64+i] <== r18.out[i];
out[19*64+i] <== r19.out[i];
out[20*64+i] <== r20.out[i];
out[21*64+i] <== r21.out[i];
out[22*64+i] <== r22.out[i];
out[23*64+i] <== r23.out[i];
out[24*64+i] <== r24.out[i];
}
}
// Iota
template RC(r) {
signal output out[64];
var rc[24] = [
0x0000000000000001, 0x0000000000008082, 0x800000000000808A,
0x8000000080008000, 0x000000000000808B, 0x0000000080000001,
0x8000000080008081, 0x8000000000008009, 0x000000000000008A,
0x0000000000000088, 0x0000000080008009, 0x000000008000000A,
0x000000008000808B, 0x800000000000008B, 0x8000000000008089,
0x8000000000008003, 0x8000000000008002, 0x8000000000000080,
0x000000000000800A, 0x800000008000000A, 0x8000000080008081,
0x8000000000008080, 0x0000000080000001, 0x8000000080008008
];
for (var i=0; i<64; i++) {
out[i] <== (rc[r] >> i) & 1;
}
}
template Iota(r) {
signal input in[25*64];
signal output out[25*64];
var i;
component rc = RC(r);
component iota = XorArray(64);
for (var i=0; i<64; i++) {
iota.a[i] <== in[i];
iota.b[i] <== rc.out[i];
}
for (i=0; i<64; i++) {
out[i] <== iota.out[i];
}
for (i=64; i<25*64; i++) {
out[i] <== in[i];
}
}

@ -1,115 +0,0 @@
pragma circom 2.0.2;
include "circomlib/circuits/gates.circom";
include "circomlib/circuits/sha256/xor3.circom";
include "circomlib/circuits/sha256/shift.circom"; // contains ShiftRight
template Xor5(n) {
signal input a[n];
signal input b[n];
signal input c[n];
signal input d[n];
signal input e[n];
signal output out[n];
var i;
component xor3 = Xor3(n);
for (i=0; i<n; i++) {
xor3.a[i] <== a[i];
xor3.b[i] <== b[i];
xor3.c[i] <== c[i];
}
component xor4 = XorArray(n);
for (i=0; i<n; i++) {
xor4.a[i] <== xor3.out[i];
xor4.b[i] <== d[i];
}
component xor5 = XorArray(n);
for (i=0; i<n; i++) {
xor5.a[i] <== xor4.out[i];
xor5.b[i] <== e[i];
}
for (i=0; i<n; i++) {
out[i] <== xor5.out[i];
}
}
template XorArray(n) {
signal input a[n];
signal input b[n];
signal output out[n];
var i;
component aux[n];
for (i=0; i<n; i++) {
aux[i] = XOR();
aux[i].a <== a[i];
aux[i].b <== b[i];
}
for (i=0; i<n; i++) {
out[i] <== aux[i].out;
}
}
template XorArraySingle(n) {
signal input a[n];
signal output out[n];
var i;
component aux[n];
for (i=0; i<n; i++) {
aux[i] = XOR();
aux[i].a <== a[i];
aux[i].b <== 1;
}
for (i=0; i<n; i++) {
out[i] <== aux[i].out;
}
}
template OrArray(n) {
signal input a[n];
signal input b[n];
signal output out[n];
var i;
component aux[n];
for (i=0; i<n; i++) {
aux[i] = OR();
aux[i].a <== a[i];
aux[i].b <== b[i];
}
for (i=0; i<n; i++) {
out[i] <== aux[i].out;
}
}
template AndArray(n) {
signal input a[n];
signal input b[n];
signal output out[n];
var i;
component aux[n];
for (i=0; i<n; i++) {
aux[i] = AND();
aux[i].a <== a[i];
aux[i].b <== b[i];
}
for (i=0; i<n; i++) {
out[i] <== aux[i].out;
}
}
template ShL(n, r) {
signal input in[n];
signal output out[n];
for (var i=0; i<n; i++) {
if (i < r) {
out[i] <== 0;
} else {
out[i] <== in[ i-r ];
}
}
}

@ -1,91 +0,0 @@
pragma circom 2.0.2;
include "../vocdoni-keccak/keccak.circom";
include "circomlib/circuits/bitify.circom";
/*
* Possibly generalizable, but for now just flatten a single pubkey from k n-bit chunks to a * single bit array
* representing the entire pubkey
*
*/
template FlattenPubkey(numBits, k) {
signal input chunkedPubkey[2][k];
signal output pubkeyBits[512];
// must be able to hold entire pubkey in input
assert(numBits*k >= 256);
// convert pubkey to a single bit array
// - concat x and y coords
// - convert each register's number to corresponding bit array
// - concatenate all bit arrays in order
component chunks2BitsY[k];
for(var chunk = 0; chunk < k; chunk++){
chunks2BitsY[chunk] = Num2Bits(numBits);
chunks2BitsY[chunk].in <== chunkedPubkey[1][chunk];
for(var bit = 0; bit < numBits; bit++){
var bitIndex = bit + numBits * chunk;
if(bitIndex < 256) {
pubkeyBits[bitIndex] <== chunks2BitsY[chunk].out[bit];
}
}
}
component chunks2BitsX[k];
for(var chunk = 0; chunk < k; chunk++){
chunks2BitsX[chunk] = Num2Bits(numBits);
chunks2BitsX[chunk].in <== chunkedPubkey[0][chunk];
for(var bit = 0; bit < numBits; bit++){
var bitIndex = bit + 256 + (numBits * chunk);
if(bitIndex < 512) {
pubkeyBits[bitIndex] <== chunks2BitsX[chunk].out[bit];
}
}
}
}
/*
* Helper for verifying an eth address refers to the correct public key point
*
* NOTE: uses https://github.com/vocdoni/keccak256-circom, a highly experimental keccak256 implementation
*/
template PubkeyToAddress() {
// public key is (x, y) curve point. this is a 512-bit little-endian bitstring representation of y + 2**256 * x
signal input pubkeyBits[512];
signal output address;
// our representation is little-endian 512-bit bitstring
// keccak template operates on bytestrings one byte at a time, starting with the biggest byte
// but bytes are represented as little-endian 8-bit bitstrings
signal reverse[512];
for (var i = 0; i < 512; i++) {
reverse[i] <== pubkeyBits[511-i];
}
component keccak = Keccak(512, 256);
for (var i = 0; i < 512 / 8; i += 1) {
for (var j = 0; j < 8; j++) {
keccak.in[8*i + j] <== reverse[8*i + (7-j)];
}
}
// convert the last 160 bits (20 bytes) into the number corresponding to address
// the output of keccak is 32 bytes. bytes are arranged from largest to smallest
// but bytes themselves are little-endian bitstrings of 8 bits
// we just want a little-endian bitstring of 160 bits
component bits2Num = Bits2Num(160);
for (var i = 0; i < 20; i++) {
for (var j = 0; j < 8; j++) {
bits2Num.in[8*i + j] <== keccak.out[256 - 8*(i+1) + j];
}
}
address <== bits2Num.out;
}

@ -1,48 +0,0 @@
pragma circom 2.1.2;
include "../poseidon/poseidon.circom";
include "circomlib/circuits/mux1.circom";
/**
* MerkleTreeInclusionProof
* ========================
*
* Copy of the Merkle Tree implementation in Semaphore:
* https://github.com/semaphore-protocol/semaphore/blob/main/packages/circuits/tree.circom
* Instead of using the circomlib Poseidon, we use our own implementation which
* uses constants specific to the secp256k1 curve.
*/
template MerkleTreeInclusionProof(nLevels) {
signal input leaf;
signal input pathIndices[nLevels];
signal input siblings[nLevels];
signal output root;
component poseidons[nLevels];
component mux[nLevels];
signal hashes[nLevels + 1];
hashes[0] <== leaf;
for (var i = 0; i < nLevels; i++) {
pathIndices[i] * (1 - pathIndices[i]) === 0;
poseidons[i] = Poseidon();
mux[i] = MultiMux1(2);
mux[i].c[0][0] <== hashes[i];
mux[i].c[0][1] <== siblings[i];
mux[i].c[1][0] <== siblings[i];
mux[i].c[1][1] <== hashes[i];
mux[i].s <== pathIndices[i];
poseidons[i].inputs[0] <== mux[i].out[0];
poseidons[i].inputs[1] <== mux[i].out[1];
hashes[i + 1] <== poseidons[i].out;
}
root <== hashes[nLevels];
}

@ -1,5 +0,0 @@
pragma circom 2.1.2;
include "../eff_ecdsa_membership/addr_membership.circom";
component main { public[ root, Tx, Ty, Ux, Uy ]} = AddrMembership(20);

@ -1,5 +0,0 @@
pragma circom 2.1.2;
include "../eff_ecdsa_membership/pubkey_membership.circom";
component main { public[ root, Tx, Ty, Ux, Uy ]} = PubKeyMembership(20);

@ -1,158 +0,0 @@
pragma circom 2.1.2;
include "./poseidon_constants.circom";
template SBox() {
signal input in;
signal output out;
signal inDouble <== in * in;
signal inQuadruple <== inDouble * inDouble;
out <== inQuadruple * in;
}
template MatrixMul() {
var t = 3;
signal input state[t];
signal output out[t];
var mds_matrix[t][t] = MDS_MATRIX();
for (var i = 0; i < t; i++) {
var tmp = 0;
for (var j = 0; j < t; j++) {
tmp += state[j] * mds_matrix[i][j];
}
out[i] <== tmp;
}
}
template AddRoundConst(pos) {
var t = 3;
signal input state[t];
signal output out[t];
var round_keys[192] = ROUND_KEYS();
for (var i = 0; i < t; i++) {
out[i] <== state[i] + round_keys[pos + i];
}
}
template FullRound(pos) {
var t = 3;
signal input state[t];
signal output out[t];
component constAdded = AddRoundConst(pos);
for (var i = 0; i < t; i++) {
constAdded.state[i] <== state[i];
}
component sBoxes[t];
for (var i = 0; i < t; i++) {
sBoxes[i] = SBox();
sBoxes[i].in <== constAdded.out[i];
}
component matrixMul = MatrixMul();
for (var i = 0; i < t; i++) {
matrixMul.state[i] <== sBoxes[i].out;
}
for (var i = 0; i < t; i++) {
out[i] <== matrixMul.out[i];
}
}
template PartialRound(pos) {
var t = 3;
signal input state[t];
signal output out[t];
component constAdded = AddRoundConst(pos);
for (var i = 0; i < t; i++) {
constAdded.state[i] <== state[i];
}
component sBox = SBox();
sBox.in <== constAdded.out[0];
component matrixMul = MatrixMul();
for (var i = 0; i < t; i++) {
if (i == 0) {
matrixMul.state[i] <== sBox.out;
} else {
matrixMul.state[i] <== constAdded.out[i];
}
}
for (var i = 0; i < t; i++) {
out[i] <== matrixMul.out[i];
}
}
template Poseidon() {
var numInputs = 2;
var t = numInputs + 1;
signal input inputs[numInputs];
var numFullRoundsHalf = 4;
var numPartialRounds = 56;
signal output out;
var stateIndex = 0;
signal initState[3];
initState[0] <== 3;
initState[1] <== inputs[0];
initState[2] <== inputs[1];
component fRoundsFirst[numFullRoundsHalf];
for (var j = 0; j < numFullRoundsHalf; j++) {
fRoundsFirst[j] = FullRound(stateIndex * t);
if (j == 0) {
for (var i = 0; i < t; i++) {
fRoundsFirst[j].state[i] <== initState[i];
}
} else {
for (var i = 0; i < t; i++) {
fRoundsFirst[j].state[i] <== fRoundsFirst[j - 1].out[i];
}
}
stateIndex++;
}
component pRounds[numPartialRounds];
for (var j = 0; j < numPartialRounds; j++) {
pRounds[j] = PartialRound(stateIndex * t);
if (j == 0) {
for (var i = 0; i < t; i++) {
pRounds[j].state[i] <== fRoundsFirst[numFullRoundsHalf - 1].out[i];
}
} else {
for (var i = 0; i < t; i++) {
pRounds[j].state[i] <== pRounds[j - 1].out[i];
}
}
stateIndex++;
}
component fRoundsLast[numFullRoundsHalf];
for (var j = 0; j < numFullRoundsHalf; j++) {
fRoundsLast[j] = FullRound(stateIndex * t);
if (j == 0) {
for (var i = 0; i < t; i++) {
fRoundsLast[j].state[i] <== pRounds[numPartialRounds - 1].out[i];
}
} else {
for (var i = 0; i < t; i++) {
fRoundsLast[j].state[i] <== fRoundsLast[j - 1].out[i];
}
}
stateIndex++;
}
out <== fRoundsLast[numFullRoundsHalf-1].out[1];
}

@ -1,218 +0,0 @@
pragma circom 2.1.2;
function ROUND_KEYS() {
return [
15180568604901803243989155929934437997245952775071395385994322939386074967328,
98155933184944822056372510812105826951789406432246960633912199752807271851218,
32585497418154084368870158853355239726261349829448673320273043226636389078017,
66713968576806622579829258440960693099797917756640662361943757758980796487698,
61296025743283504825054745787375839406507895949474930140819919915792438454216,
64548089412749542282115556935384382035671782881737715696939837764375912217104,
108421562972909537718478936575770973463273651828765393113349044862621092658552,
93957623861448681916560847065407918286434708744548934125771289238599801659600,
31886767595881910145119755249133120645312710313371225820300496900248094187131,
36511615103248888903406040506250394762206798360602726106046630438239169384653,
21193239787133737740669439860809806837993750509086389566475677877580362491125,
15159189447883181997488877417695825734356570617827322308691834229181804753656,
19272373877630561389686073945290625876718814210798194797601715657476609730306,
23132197996397121955527964729507651432518694856862854469217474256539272053037,
9869753235007825662020275771343858285582964429845049469800863115040150206544,
36536341316285671890133896506951910369952562161551585116256678375995315827743,
62582239167707347777855528698896708360409296899261565735324151945083720570858,
96597358901965097853721114962031771931271685249979807653919643952343419105640,
99475971754252188104003224702005940217163363685728394033034788135108600073953,
52080483875928847502018688921126796935417602445765802481027972679966274137987,
101922748752417217354391348649359865075718358385248454632698502400961567227929,
26980595292132221181330746499613907829041623688147011560382352796984836870749,
7059991836806083192408106370472821784612460308866802565871813230060135266390,
19329812920723038526370491239817117039289784665617181727933894076969997926129,
65570620823578601926240439251563587376966657231502120214692324496443514623818,
58403733332589349613112270854204921427257113546270812628317365115158685715742,
45021021211732634759643776743541935700591354899980928498981462362035961745443,
313468157086800401026946312285365733155132234906935411743639256319782592571,
101316949793045093761117346380310841944294663456931203380573537653884068660109,
23683935571424619534194393788101669168630123784066421490798386323411538828592,
45470730427236677197026094498490008082250264942279323465121581539984407294442,
48141067373531800337373447278127981363951468257064369512416205750641258258193,
42554919225040466028330117313396362347164995917041931400909482795914116747618,
11551941832988244108260444347046942236051939264069344013774353630451796870907,
60185799182545404739011626517355854847787627814101363386450657535504094743765,
81823160578900678880708744457872721685515019032370491632046212317701226128393,
7165646831054215773988859638722974820791178194871546344315162343128362695647,
75289707601640398424243937567716657896680380639974371761136292031415717685949,
7150842764562742184396161198129263121409208675362553300851082062734889620953,
24380904705269761063866540342138412601132455197711667167747524315310027386226,
9728986075621437350131504894128984146939551938810073671231633620616345344412,
10579382052089733216628873394134968879891026686695240299956972154694558493896,
8171994519466002143995890536756742287314780571933910736618431096190430536601,
30420144259409274775063072923609924427757612539094840146996944760708902708570,
63962155989812703023698320394024694856871261481871757094333286947755599007133,
25280070391177856032024336895094721131222985610587247589336316615596140400436,
15305872319988027006162258914083163651002306183917888172691618513722838997098,
51545603291342006705870081001071419395633279951502747769141857387796043104608,
91109680756552587805002537489407348773333405839144382221272597323798859182191,
72175452855185658158184807496160149169667221240389196996344579971523681433202,
30361989157454953234766224747536334157139256334148153290771332849307087761025,
38169634499980959088614671703639492517637815232220682121652135514105493936992,
49591153263237620796156788742811547511792615129981565620486914545749079774827,
47403873018260745456113868791119169163627014766514972598212646481717066065016,
93989849689047144228924801010853106857960399638657695410345207191739048300111,
10590240512802509131776989274411792739339398409955259174829387591089799115255,
29183703335869638067547208413224742887766212046438654772943025958628178245227,
4131650227136944095885036960767735080970262672750406866066212532739784907379,
43395510588213653537697670365796375057855260611965666448183946252832290017444,
95246795133940226900907730059125298420936467652619708443128629427116119621152,
6012209003558496814495903476753006089125143165365334812097313083703216071080,
26183233284429251459198269925441295879550203824094631575778521083706115817955,
26058994700533582730528567480051558438548299522338811756875396252016497202713,
107240485663145290290374164860301805857261278222480421976433215167444496066511,
84412820763898503096477800002865877536719992495674955119188074297975154406587,
52386303852182662900790700046090769869460994629239741773176060026198900130384,
95746062835936512160025091603469309809932540674474329021370075533568318932379,
22711334660013961010382652754865456251782349529764119853461446587583972054666,
16959835233095757670013367728627149851239789174357906293937455553277911805495,
15116421110200928832147360650392633091242147433006813656250997138988179879750,
107878787525302837370688492081178689950008165750500003692400517211520334656293,
44210105558575948369921579518078229089923760124167628288943900602376706136436,
90305995748749060889452130219544332384396626628663475498252761213618628372367,
104941997925797907872686462815914481945432760720471803254797908465921520138024,
100036855232527386145662094141100441220151775745916101660987264242446845728894,
103285582836474146806606752170525767341430483568396209591447274936228630298052,
82197692939371228160449741709034077803239992888716859217989995857278406253737,
10040764964044995095453717286623030376397745892179877153575434454090155545240,
27304226040425863042893623786832369758179176309230053449707879364285977952630,
42627232144930751842910170221862679057276668485045156742021958050665662768084,
76972394926916659428228833084621905890924612368412796262119501852346293848159,
39796921406297542196667238133893946368231540421737718098283349901435707131075,
14745047092916651495052563068083093689676472592445845983334785004125684263162,
43421479365783318841667739359312715738029447177150400204380817518608837765863,
107871536756946365977710326147511195471121248998432910212631960353348700694610,
39505942243687894211614489736115535754716239859353578295470352855493707198619,
59676442091621150164811367352362126934419932715789994860508056194143441226580,
94470526851498636320865653968033227263836954414283116133326109455334870036212,
15044796858044094866329855531761112645684343559112419720568996573556805975600,
67157729293641241473980125231288476062565688273917759533572275886277269201651,
72911083146182058225942884942982388217243826839805061121973109250798137784134,
102973386186208530972563015865701244407271836208547629083437627219683649557477,
57485522356347377122696081086816661784954498123948319434326439317393351620564,
23112275556906805064863694321486306070917598599342299357379251070160695202292,
107618884362423342584703700349292347754139538760798319916678240538294838342400,
83961260400031958812820990908241261093246389047082613562825737834833753517337,
42726953951733266282750892844947149703751388034177248277671157488506520215317,
39379570934119946602507737250800178347029772561352879974941214627084076473292,
72203650529122342092280763801468513707870760755235719535090090101623606334441,
13389660788942842724553143053013919883368472759564135119390935439369513690496,
101745263541280877725997503552978999350831489463993178838531539940805924817361,
76849182334465191824607032600721023780793694103840553871800174717760598910761,
53896256317996838683363773836826653859512780625932638736752563553878867538095,
24688792501674999263943657175455335814404948006469220532686392550824320454904,
69132683906595821927803530074656979217668636557563597358799899743174233903941,
2861982085506615225917620192781928414994576134281371548401916333754363567986,
37311353286221616083824584705974993449107063556724405440534160586561042968316,
83718085796857523832195255218519255973031752296424117786202083986118546906913,
103633177691684814414226251117070754499104739002759424774194851613917008856616,
84968411062305024171594435878414659990735518025357685215223731503921265946461,
41865099330909055069143724769818364262362915440371474104937435863183989905059,
46156624920251322979270606388518884047396423747179340919303543598300663968593,
64416327466854458915398302811825971539792429791049027619471115285308743811583,
94942471312481523091911417289540395651121558150571128515230470225155209280585,
109682618775735319282534546194470743032129102295907200313471041846112653687024,
61531999191737540795124202104235799899980935519651613893518293245268304980543,
17797352534596268622733030076742840951214734697361029060619245779495726996632,
2323150752778983462106829021155031678603044899339819935981200101818542000989,
16998018904363448507967526489917057882529252665835717172712095240271574074587,
110634872413902251217040490777568744431854972018399530234679399294372694506842,
31639545145649753705216327198217551838008233610574104460826956396569310697060,
107845103764339268987018917144483935480716224058844669233389185480836000033760,
46240297572174662698030819651333060930818959915797061274854448535534474175039,
53065607123105696930220421963755520777674094852857308823370049733888025985616,
16931881300947470270453776207625163368485560075525342751440832370220475352149,
79254110800481916763656344422402393723573490114487681345184594841431920461089,
42268569642639492314994307446626647824927989776691987788682655102426770655233,
9749633319307409894058984489496091535125232227316143918000642155415596066903,
57606597628648270579042266322415267200058617178318601782866227410456726724976,
56082250485913115488341301630850455009935943641292622301678990296508134206571,
17957245764842844288802777667800779232762688847417238921175068882796163705248,
94356229516444419318132697346021621194464273500135725160277725602263001442644,
52536631226748676066386651084538409050048707922045928887930261833545619358914,
107794922118166328243581272159394479176678094739027519706768813902978100436849,
92984368734102511759118281503078145182557799453616537383408606074187034371208,
59652553897137603386525572460411404882917571255327541516871354737502335133690,
49012645345644326995052653072578673750516379655033952006121214224119466671764,
79025576845143484310735291619293962982804358365838961371044480386743856799994,
5437377540613244374799729812489584777222423091155743557287567155811057717409,
100687592213090267900708728796310211082532607828753010566886681655775031329660,
99074462968857696481475128596339544396152341206708424767062829343406495063192,
67476872698289965626550204192782761730653024363949045140720348870736942130242,
103307125141718054130755829916960708430672826104789971350239945481960770107890,
74087383014714668160537499936376991041273055222568604413015844459913259357334,
40924049099780965904051946083599822761993164889139026432053420731164022206736,
32594924940463736641240515015317856157169105212942308502676422036626316673214,
98990663138035055774586216545398054668349058134877723031747421828753359974443,
55821766022768786066770462759796825978667805772707620106340033118519147871694,
4001942224536365489828915551180230767516454384395893814399938353050969198154,
30136373426492646221252150708518703998248891683881870400906269276900707426865,
34943205764464817266133164313915763122699935186597909347522822673832250079664,
27737330737483170511275902246508559278973986181590368845166383812793468814968,
96292398813565494438359802278723334615526914389306923046282571355958508916558,
97147334956505986101750230325438660094766812949748276042292963837380833668274,
24754519562402723848413674701792328284127274989440581643644298347747941238812,
76111103490248669364580390783887028636436246028943665707064153006971943621186,
33764090322658516047637223655525551979364055499647855895233821795694749902854,
100536990630540359004783976190215234627391515555181073681294901127179838732969,
55991997435987096996680289872758998763908676069536901375395297778729059185671,
32860959903680178324832991459746631238726690317249285658471597044247794502256,
70074816806976994707467706079200635184034023598764203123459335544110485476930,
46213940675829172331116620705134022102338250410334045747023950259088879662946,
77000624259024986585504351395777746568094934279771127334532438603183524642061,
21719649576090832101273013788716623377603297433777804572370785470329817725170,
29209622978540575483991966565508890231057362045066230397327380085945876837821,
2445742484263083651472035320255578071935687960412507452207899496253120999364,
86846812580007547526361109808384103509272544750564766849178767957571523649544,
43025640639926253696325070988523609146060819319830735794100778654425057363895,
108957662689228031021948854644435971168708642184764962508575441689859324862868,
83891545396650121758556392255189778590486277180642660527000882403085396114823,
42527013475786190604202451803064937203698027000671529418992521798122995373551,
115180194520889678365425151865713593680657747284471744934804370945935167043862,
28979598171177052880917135045920701144584888536299261666846302083645491369348,
68351312608110279019109436395199010412431777911149851157132527077210966351650,
61759623963943995967580147094342313397376358019837276043205235302342147116585,
80714625408576660514217469096827255752431164791924432025682445176737446783085,
33048555646676368266608424610100449208381357250300222636992099726804869416731,
50682223610667325089810868083131721901859473966415125289975106060759036109476,
4271213571706787092297985431667190050727614825584809797590204884727103716461,
101314046722405990971733763321368296660561930294000591067108115987088407142646,
55565500177602146197728150332647093173137211885612327122425918553270191254877,
65556764608648687291293889343854786421750589271167654521933267288313526422497,
66877533773422945979143954094644173219583178339199697252673545117318799706373,
30511098623357801425494143655999121699575856091238269679669864984061501512835,
95900192636363991637086954986559552472749485926252879461208179855482821976623,
37879946127489462347049192209554168578320892231852882971030128420645686965013,
80479504274334215471057938992198620419540634144266821121799003865782336406529,
13326262422954139210095783388743602482455840337093117010479445267213907605425,
16047106134611124637925332265703907202779549268127518502853950466090054176776,
71499356105233640605079063493613576024353801558965221134519779175477723594865,
28438981751956157476540225984733791304599172905715743025543841239013139121102,
56066317647068426981453448715118237747130321302262827290362392918472904421147
];
}
function MDS_MATRIX() {
return [
[
92469348809186613947252340883344274339611751744959319352506666082431267346705,
100938028378191533449096235266991198229563815869344032449592738345766724371160,
77486311749148948616988559783475694076613010381924638436641318334458515006661
],
[
110352262556914082363749654180080464794716701228558638957603951672835474954408,
27607004873684391669404739690441550149894883072418944161048725383958774443141,
29671705769502357195586268679831947082918094959101307962374709600277676341325
],
[
77762103796341032609398578911486222569419103128091016773380377798879650228751,
1753012011204964731088925227042671869111026487299375073665493007998674391999,
70274477372358662369456035572054501601454406272695978931839980644925236550307
]
];
}

@ -1,44 +0,0 @@
export default async () => {
return {
// @ts-ignore
'circuits/eff_ecdsa_membership/secp256k1/add.circom': (await import('raw-loader!./circuits/eff_ecdsa_membership/secp256k1/add.circom')).default,
// @ts-ignore
'circuits/eff_ecdsa_membership/secp256k1/double.circom': (await import('!!raw-loader!./circuits/eff_ecdsa_membership/secp256k1/double.circom')).default,
// @ts-ignore
'circuits/eff_ecdsa_membership/secp256k1/mul.circom': (await import('!!raw-loader!./circuits/eff_ecdsa_membership/secp256k1/mul.circom')).default,
// @ts-ignore
'circuits/eff_ecdsa_membership/to_address/vocdoni-keccak/keccak.circom': (await import('!!raw-loader!./circuits/eff_ecdsa_membership/to_address/vocdoni-keccak/keccak.circom')).default,
// @ts-ignore
'circuits/eff_ecdsa_membership/to_address/vocdoni-keccak/permutations.circom': (await import('!!raw-loader!./circuits/eff_ecdsa_membership/to_address/vocdoni-keccak/permutations.circom')).default,
// @ts-ignore
'circuits/eff_ecdsa_membership/to_address/vocdoni-keccak/utils.circom': (await import('!!raw-loader!./circuits/eff_ecdsa_membership/to_address/vocdoni-keccak/utils.circom')).default,
// @ts-ignore
'circuits/eff_ecdsa_membership/to_address/zk-identity/eth.circom': (await import('!!raw-loader!./circuits/eff_ecdsa_membership/to_address/zk-identity/eth.circom')).default,
// @ts-ignore
'circuits/eff_ecdsa_membership/addr_membership.circom': (await import('!!raw-loader!./circuits/eff_ecdsa_membership/addr_membership.circom')).default,
// @ts-ignore
'circuits/eff_ecdsa_membership/eff_ecdsa_to_addr.circom': (await import('!!raw-loader!./circuits/eff_ecdsa_membership/eff_ecdsa_to_addr.circom')).default,
// @ts-ignore
'circuits/eff_ecdsa_membership/eff_ecdsa.circom': (await import('!!raw-loader!./circuits/eff_ecdsa_membership/eff_ecdsa.circom')).default,
// @ts-ignore
'circuits/eff_ecdsa_membership/pubkey_membership.circom': (await import('!!raw-loader!./circuits/eff_ecdsa_membership/pubkey_membership.circom')).default,
// @ts-ignore
'circuits/eff_ecdsa_membership/tree.circom': (await import('!!raw-loader!./circuits/eff_ecdsa_membership/tree.circom')).default,
// @ts-ignore
'circuits/instances/addr_membership.circom': (await import('!!raw-loader!./circuits/instances/addr_membership.circom')).default,
// @ts-ignore
'circuits/instances/pubkey_membership.circom': (await import('!!raw-loader!./circuits/instances/pubkey_membership.circom')).default,
// @ts-ignore
'circuits/poseidon/poseidon_constants.circom': (await import('!!raw-loader!./circuits/poseidon/poseidon_constants.circom')).default,
// @ts-ignore
'circuits/poseidon/poseidon.circom': (await import('!!raw-loader!./circuits/poseidon/poseidon.circom')).default,
// @ts-ignore
'scripts/run_setup.ts': (await import('!!raw-loader!./scripts/run_setup.ts')).default,
// @ts-ignore
'scripts/run_verification.ts': (await import('!!raw-loader!./scripts/run_verification.ts')).default,
// @ts-ignore
'templates/groth16_verifier.sol.ejs': (await import('!!raw-loader!./templates/groth16_verifier.sol.ejs')).default,
// @ts-ignore
'README.md': (await import('raw-loader!./README.md')).default
}
}

@ -1,56 +0,0 @@
import { ethers, BigNumber } from 'ethers'
// eslint-disable-next-line @typescript-eslint/no-var-requires
const snarkjs = require('snarkjs');
(async () => {
try {
// @ts-ignore
await remix.call('circuit-compiler', 'generateR1cs', 'circuits/instances/pubkey_membership.circom');
const ptau_final = "https://ipfs-cluster.ethdevops.io/ipfs/QmTiT4eiYz5KF7gQrDsgfCSTRv3wBPYJ4bRN1MmTRshpnW";
// @ts-ignore
const r1csBuffer = await remix.call('fileManager', 'readFile', 'circuits/instances/.bin/pubkey_membership.r1cs', true);
// @ts-ignore
const r1cs = new Uint8Array(r1csBuffer);
const zkey_0 = { type: "mem" };
const zkey_1 = { type: "mem" };
const zkey_final = { type: "mem" };
console.log('newZkey')
await snarkjs.zKey.newZKey(r1cs, ptau_final, zkey_0);
console.log('contribute')
await snarkjs.zKey.contribute(zkey_0, zkey_1, "p2_C1", "pa_Entropy1");
console.log('beacon')
await snarkjs.zKey.beacon(zkey_1, zkey_final, "B3", "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", 10);
console.log('verifyFromR1cs')
const verifyFromR1csResult = await snarkjs.zKey.verifyFromR1cs(r1cs, ptau_final, zkey_final);
console.assert(verifyFromR1csResult);
console.log('verifyFromInit')
const verifyFromInit = await snarkjs.zKey.verifyFromInit(zkey_0, ptau_final, zkey_final);
console.assert(verifyFromInit);
console.log('exportVerificationKey')
const vKey = await snarkjs.zKey.exportVerificationKey(zkey_final)
await remix.call('fileManager', 'writeFile', './zk/build/verification_key.json', JSON.stringify(vKey))
const templates = {
groth16: await remix.call('fileManager', 'readFile', 'templates/groth16_verifier.sol.ejs')
}
const solidityContract = await snarkjs.zKey.exportSolidityVerifier(zkey_final, templates)
await remix.call('fileManager', 'writeFile', './zk/build/zk_verifier.sol', solidityContract)
console.log('buffer', (zkey_final as any).data.length)
await remix.call('fileManager', 'writeFile', './zk/build/zk_setup.txt', JSON.stringify(Array.from(((zkey_final as any).data))))
console.log('setup done.')
} catch (e) {
console.error(e.message)
}
})()

@ -1,122 +0,0 @@
// @ts-ignore
import { Poseidon, Tree, computeEffEcdsaPubInput } from "@personaelabs/spartan-ecdsa"
// @ts-ignore
import { privateToPublic, hashPersonalMessage, ecsign, utf8ToBytes, bytesToHex } from "@ethereumjs/util"
// eslint-disable-next-line @typescript-eslint/no-var-requires
const snarkjs = require('snarkjs');
const logger = {
info: (...args) => console.log(...args),
debug: (...args) => console.log(...args),
error: (...args) => console.error(...args),
}
function getEffEcdsaCircuitInput (privKey, msg) {
const msgHash = hashPersonalMessage(msg)
const { v, r: _r, s } = ecsign(msgHash, privKey)
const r = BigInt('0x' + _r.map(byte => byte.toString(16).padStart(2, '0')).join(''))
const circuitPubInput = computeEffEcdsaPubInput(r, v, msgHash)
const input = {
s: BigInt('0x' + s.map(byte => byte.toString(16).padStart(2, '0')).join('')),
Tx: circuitPubInput.Tx,
Ty: circuitPubInput.Ty,
Ux: circuitPubInput.Ux,
Uy: circuitPubInput.Uy
}
return input
}
(async () => {
try {
// @ts-ignore
const r1csBuffer = await remix.call('fileManager', 'readFile', 'circuits/instances/.bin/pubkey_membership.r1cs', true)
// @ts-ignore
const r1cs = new Uint8Array(r1csBuffer)
// @ts-ignore
const wasmBuffer = await remix.call('fileManager', 'readFile', 'circuits/instances/.bin/pubkey_membership.wasm', true)
// @ts-ignore
const wasm = new Uint8Array(wasmBuffer)
const zkey_final = {
type: "mem",
data: new Uint8Array(JSON.parse(await remix.call('fileManager', 'readFile', './zk/build/zk_setup.txt')))
}
const wtns = { type: "mem" }
const vKey = JSON.parse(await remix.call('fileManager', 'readFile', './zk/build/verification_key.json'))
// Construct the tree
const poseidon = new Poseidon()
await poseidon.initWasm()
const nLevels = 10
const tree = new Tree(nLevels, poseidon)
console.log('done')
const privKeys = [
utf8ToBytes("".padStart(16, "🧙")),
utf8ToBytes("".padStart(16, "🪄")),
utf8ToBytes("".padStart(16, "🔮"))
]
// Store public key hashes
const pubKeyHashes: bigint[] = []
// Compute public key hashes
for (const privKey of privKeys) {
const pubKey = privateToPublic(privKey)
const pubKeyHex = bytesToHex(pubKey)
const hexWithoutPrefix = pubKeyHex.startsWith('0x') ? pubKeyHex.slice(2) : pubKeyHex;
const pubKeyHash = poseidon.hashPubKey(hexWithoutPrefix)
pubKeyHashes.push(pubKeyHash)
}
// Insert the pubkey hashes into the tree
for (const pubKeyHash of pubKeyHashes) {
tree.insert(pubKeyHash)
}
// Sign
const index = 0; // Use privKeys[0] for proving
const privKey = privKeys[index]
const msg = utf8ToBytes("hello world".padStart(16, " "))
// Prepare signature proof input
const effEcdsaInput = getEffEcdsaCircuitInput(privKey, msg)
const merkleProof = tree.createProof(index)
const signals = {
...effEcdsaInput,
siblings: merkleProof.siblings,
pathIndices: merkleProof.pathIndices,
root: tree.root()
}
console.log('signals: ', signals)
console.log('calculate')
await snarkjs.wtns.calculate(signals, wasm, wtns)
// console.log('check')
// await snarkjs.wtns.check(r1cs, wtns, logger)
// console.log('prove')
// const { proof, publicSignals } = await snarkjs.groth16.prove(zkey_final, wtns);
// const verified = await snarkjs.groth16.verify(vKey, publicSignals, proof, logger);
// console.log('zk proof validity', verified);
// proof1.root.toString() === publicSignals[0] ? console.log('merkle proof valid') : console.log('merkle proof invalid')
} catch (e) {
console.error(e.message)
}
})()

@ -1,165 +0,0 @@
// SPDX-License-Identifier: GPL-3.0
/*
Copyright 2021 0KIMS association.
This file is generated with [snarkJS](https://github.com/iden3/snarkjs).
snarkJS is a free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
snarkJS is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
*/
pragma solidity >=0.7.0 <0.9.0;
contract Groth16Verifier {
// Scalar field size
uint256 constant r = 21888242871839275222246405745257275088548364400416034343698204186575808495617;
// Base field size
uint256 constant q = 21888242871839275222246405745257275088696311157297823662689037894645226208583;
// Verification Key data
uint256 constant alphax = <%= vk_alpha_1[0] %>;
uint256 constant alphay = <%= vk_alpha_1[1] %>;
uint256 constant betax1 = <%= vk_beta_2[0][1] %>;
uint256 constant betax2 = <%= vk_beta_2[0][0] %>;
uint256 constant betay1 = <%= vk_beta_2[1][1] %>;
uint256 constant betay2 = <%= vk_beta_2[1][0] %>;
uint256 constant gammax1 = <%= vk_gamma_2[0][1] %>;
uint256 constant gammax2 = <%= vk_gamma_2[0][0] %>;
uint256 constant gammay1 = <%= vk_gamma_2[1][1] %>;
uint256 constant gammay2 = <%= vk_gamma_2[1][0] %>;
uint256 constant deltax1 = <%= vk_delta_2[0][1] %>;
uint256 constant deltax2 = <%= vk_delta_2[0][0] %>;
uint256 constant deltay1 = <%= vk_delta_2[1][1] %>;
uint256 constant deltay2 = <%= vk_delta_2[1][0] %>;
<% for (let i=0; i<IC.length; i++) { %>
uint256 constant IC<%=i%>x = <%=IC[i][0]%>;
uint256 constant IC<%=i%>y = <%=IC[i][1]%>;
<% } %>
// Memory data
uint16 constant pVk = 0;
uint16 constant pPairing = 128;
uint16 constant pLastMem = 896;
function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[<%=IC.length-1%>] calldata _pubSignals) public view returns (bool) {
assembly {
function checkField(v) {
if iszero(lt(v, q)) {
mstore(0, 0)
return(0, 0x20)
}
}
// G1 function to multiply a G1 value(x,y) to value in an address
function g1_mulAccC(pR, x, y, s) {
let success
let mIn := mload(0x40)
mstore(mIn, x)
mstore(add(mIn, 32), y)
mstore(add(mIn, 64), s)
success := staticcall(sub(gas(), 2000), 7, mIn, 96, mIn, 64)
if iszero(success) {
mstore(0, 0)
return(0, 0x20)
}
mstore(add(mIn, 64), mload(pR))
mstore(add(mIn, 96), mload(add(pR, 32)))
success := staticcall(sub(gas(), 2000), 6, mIn, 128, pR, 64)
if iszero(success) {
mstore(0, 0)
return(0, 0x20)
}
}
function checkPairing(pA, pB, pC, pubSignals, pMem) -> isOk {
let _pPairing := add(pMem, pPairing)
let _pVk := add(pMem, pVk)
mstore(_pVk, IC0x)
mstore(add(_pVk, 32), IC0y)
// Compute the linear combination vk_x
<% for (let i = 1; i <= nPublic; i++) { %>
g1_mulAccC(_pVk, IC<%=i%>x, IC<%=i%>y, calldataload(add(pubSignals, <%=(i-1)*32%>)))
<% } %>
// -A
mstore(_pPairing, calldataload(pA))
mstore(add(_pPairing, 32), mod(sub(q, calldataload(add(pA, 32))), q))
// B
mstore(add(_pPairing, 64), calldataload(pB))
mstore(add(_pPairing, 96), calldataload(add(pB, 32)))
mstore(add(_pPairing, 128), calldataload(add(pB, 64)))
mstore(add(_pPairing, 160), calldataload(add(pB, 96)))
// alpha1
mstore(add(_pPairing, 192), alphax)
mstore(add(_pPairing, 224), alphay)
// beta2
mstore(add(_pPairing, 256), betax1)
mstore(add(_pPairing, 288), betax2)
mstore(add(_pPairing, 320), betay1)
mstore(add(_pPairing, 352), betay2)
// vk_x
mstore(add(_pPairing, 384), mload(add(pMem, pVk)))
mstore(add(_pPairing, 416), mload(add(pMem, add(pVk, 32))))
// gamma2
mstore(add(_pPairing, 448), gammax1)
mstore(add(_pPairing, 480), gammax2)
mstore(add(_pPairing, 512), gammay1)
mstore(add(_pPairing, 544), gammay2)
// C
mstore(add(_pPairing, 576), calldataload(pC))
mstore(add(_pPairing, 608), calldataload(add(pC, 32)))
// delta2
mstore(add(_pPairing, 640), deltax1)
mstore(add(_pPairing, 672), deltax2)
mstore(add(_pPairing, 704), deltay1)
mstore(add(_pPairing, 736), deltay2)
let success := staticcall(sub(gas(), 2000), 8, _pPairing, 768, _pPairing, 0x20)
isOk := and(success, mload(_pPairing))
}
let pMem := mload(0x40)
mstore(0x40, add(pMem, pLastMem))
// Validate that all evaluations ∈ F
<% for (let i=0; i<IC.length; i++) { %>
checkField(calldataload(add(_pubSignals, <%=i*32%>)))
<% } %>
// Validate all evaluations
let isValid := checkPairing(_pA, _pB, _pC, _pubSignals, pMem)
mstore(0, isValid)
return(0, 0x20)
}
}
}
Loading…
Cancel
Save