This commit is contained in:
s1fr0 2022-06-02 19:54:07 +02:00
parent 4638ac51d8
commit 49893de561
No known key found for this signature in database
GPG Key ID: 2C041D60117BFF46
9 changed files with 411 additions and 2 deletions

View File

@ -1,5 +1,5 @@
#!/bin/bash
CIRCOM_BASE=~/circom2
CIRCOM_BASE=./
DEFAULT_FILENAME=$1
rm -rf $CIRCOM_BASE/$1
mkdir -p $CIRCOM_BASE/$1/src

View File

@ -0,0 +1,56 @@
PROJECT_NAME := $(notdir $(PWD))
DEFAULT_FILENAME=$(PROJECT_NAME)
PROJECT_DIR := $(PWD)
BUILD_DIR=$(PROJECT_DIR)/build
WITNESS_DIR=$(PROJECT_DIR)/witness
KEYS_DIR=$(PROJECT_DIR)/keys
POT_DIR=$(PROJECT_DIR)/../powersoftau
PROOFS_DIR=$(PROJECT_DIR)/proofs
POT_CONTR=$(POT_DIR)/pot12_0001.ptau $(POT_DIR)/pot12_final.ptau
POT_VERBOSE= #-v
all: js
clean:
@rm -rf $(PROJECT_DIR)/build/*
@rm -rf $(PROJECT_DIR)/keys/*
@rm -rf $(PROJECT_DIR)/proofs/*
@rm -rf $(PROJECT_DIR)/witness/*
js:
@circom $(PROJECT_DIR)/src/$(DEFAULT_FILENAME).circom --r1cs --wasm --sym -o $(BUILD_DIR)
@node $(BUILD_DIR)/$(DEFAULT_FILENAME)_js/generate_witness.js $(BUILD_DIR)/$(DEFAULT_FILENAME)_js/$(DEFAULT_FILENAME).wasm $(PROJECT_DIR)/input.json $(WITNESS_DIR)/witness.wtns
@snarkjs powersoftau prepare phase2 $(POT_CONTR) $(POT_VERBOSE)
@snarkjs groth16 setup $(BUILD_DIR)/$(DEFAULT_FILENAME).r1cs $(POT_DIR)/pot12_final.ptau $(KEYS_DIR)/$(DEFAULT_FILENAME)_0000.zkey
@openssl rand -base64 64 > $(BUILD_DIR)/rand.input
@snarkjs zkey contribute $(KEYS_DIR)/$(DEFAULT_FILENAME)_0000.zkey $(KEYS_DIR)/$(DEFAULT_FILENAME)_0001.zkey --name="1st Contributor" < $(BUILD_DIR)/rand.input
@rm -f $(BUILD_DIR)/rand.input
@snarkjs zkey export verificationkey $(KEYS_DIR)/$(DEFAULT_FILENAME)_0001.zkey $(KEYS_DIR)/verification_key.json
@snarkjs groth16 prove $(KEYS_DIR)/$(DEFAULT_FILENAME)_0001.zkey $(WITNESS_DIR)/witness.wtns $(PROOFS_DIR)/proof.json $(PROOFS_DIR)/public.json
@snarkjs groth16 verify $(KEYS_DIR)/verification_key.json $(PROOFS_DIR)/public.json $(PROOFS_DIR)/proof.json
c:
@circom $(PROJECT_DIR)/src/$(DEFAULT_FILENAME).circom --r1cs --sym --c -o $(BUILD_DIR)/
@make -C $(BUILD_DIR)/$(DEFAULT_FILENAME)_cpp/
@$(BUILD_DIR)/$(DEFAULT_FILENAME)_cpp/$(DEFAULT_FILENAME) $(PROJECT_DIR)/input.json $(WITNESS_DIR)/witness.wtns
@snarkjs powersoftau prepare phase2 $(POT_CONTR) $(POT_VERBOSE)
@snarkjs groth16 setup $(BUILD_DIR)/$(DEFAULT_FILENAME).r1cs $(POT_DIR)/pot12_final.ptau $(KEYS_DIR)/$(DEFAULT_FILENAME)_0000.zkey
@openssl rand -base64 64 > $(BUILD_DIR)/rand.input
@snarkjs zkey contribute $(KEYS_DIR)/$(DEFAULT_FILENAME)_0000.zkey $(KEYS_DIR)/$(DEFAULT_FILENAME)_0001.zkey --name="1st Contributor" < $(BUILD_DIR)/rand.input
@rm -f $(BUILD_DIR)/rand.input
@snarkjs zkey export verificationkey $(KEYS_DIR)/$(DEFAULT_FILENAME)_0001.zkey $(KEYS_DIR)/verification_key.json
@snarkjs groth16 prove $(KEYS_DIR)/$(DEFAULT_FILENAME)_0001.zkey $(WITNESS_DIR)/witness.wtns $(PROOFS_DIR)/proof.json $(PROOFS_DIR)/public.json
@snarkjs groth16 verify $(KEYS_DIR)/verification_key.json $(PROOFS_DIR)/public.json $(PROOFS_DIR)/proof.json
circuit:
@circom $(PROJECT_DIR)/src/$(DEFAULT_FILENAME).circom --r1cs --wasm --sym -o $(BUILD_DIR)
witness:
@node $(BUILD_DIR)/$(DEFAULT_FILENAME)_js/generate_witness.js $(BUILD_DIR)/$(DEFAULT_FILENAME)_js/$(DEFAULT_FILENAME).wasm $(PROJECT_DIR)/input.json $(WITNESS_DIR)/witness.wtns
proof:
@node $(BUILD_DIR)/$(DEFAULT_FILENAME)_js/generate_witness.js $(BUILD_DIR)/$(DEFAULT_FILENAME)_js/$(DEFAULT_FILENAME).wasm $(PROJECT_DIR)/input.json $(WITNESS_DIR)/witness.wtns
@snarkjs groth16 prove $(KEYS_DIR)/$(DEFAULT_FILENAME)_0001.zkey $(WITNESS_DIR)/witness.wtns $(PROOFS_DIR)/proof.json $(PROOFS_DIR)/public.json
@snarkjs groth16 verify $(KEYS_DIR)/verification_key.json $(PROOFS_DIR)/public.json $(PROOFS_DIR)/proof.json
.PHONY: all clean js c witness proof

View File

@ -0,0 +1,40 @@
{
"identity_secret": "12825549237505733615964533204745049909430608936689388901883576945030025938736",
"path_elements": [
"18622655742232062119094611065896226799484910997537830749762961454045300666333",
"20590447254980891299813706518821659736846425329007960381537122689749540452732",
"7423237065226347324353380772367382631490014989348495481811164164159255474657",
"11286972368698509976183087595462810875513684078608517520839298933882497716792",
"3607627140608796879659380071776844901612302623152076817094415224584923813162",
"19712377064642672829441595136074946683621277828620209496774504837737984048981",
"20775607673010627194014556968476266066927294572720319469184847051418138353016",
"3396914609616007258851405644437304192397291162432396347162513310381425243293",
"21551820661461729022865262380882070649935529853313286572328683688269863701601",
"6573136701248752079028194407151022595060682063033565181951145966236778420039",
"12413880268183407374852357075976609371175688755676981206018884971008854919922",
"14271763308400718165336499097156975241954733520325982997864342600795471836726",
"20066985985293572387227381049700832219069292839614107140851619262827735677018",
"9394776414966240069580838672673694685292165040808226440647796406499139370960",
"11331146992410411304059858900317123658895005918277453009197229807340014528524"
],
"identity_path_index": [
1,
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
"x": "8143228284048792769012135629627737459844825626241842423967352803501040982",
"epoch": "0x0000005b612540fc986b42322f8cb91c2273afad58ed006fdba0c97b4b16b12f",
"rln_identifier": "11412926387081627876309792396682864042420635853496105400039841573530884328439"
}

View File

@ -0,0 +1,65 @@
pragma circom 2.0.0;
include "../node_modules/circomlib/circuits/poseidon.circom";
include "../node_modules/circomlib/circuits/mux1.circom";
template PoseidonHashT3() {
var nInputs = 2;
signal input inputs[nInputs];
signal output out;
component hasher = Poseidon(nInputs);
for (var i = 0; i < nInputs; i ++) {
hasher.inputs[i] <== inputs[i];
}
out <== hasher.out;
}
template HashLeftRight() {
signal input left;
signal input right;
signal output hash;
component hasher = PoseidonHashT3();
left ==> hasher.inputs[0];
right ==> hasher.inputs[1];
hash <== hasher.out;
}
template MerkleTreeInclusionProof(n_levels) {
signal input leaf;
signal input path_index[n_levels];
signal input path_elements[n_levels][1];
signal output root;
component hashers[n_levels];
component mux[n_levels];
signal levelHashes[n_levels + 1];
levelHashes[0] <== leaf;
for (var i = 0; i < n_levels; i++) {
// Should be 0 or 1
path_index[i] * (1 - path_index[i]) === 0;
hashers[i] = HashLeftRight();
mux[i] = MultiMux1(2);
mux[i].c[0][0] <== levelHashes[i];
mux[i].c[0][1] <== path_elements[i][0];
mux[i].c[1][0] <== path_elements[i][0];
mux[i].c[1][1] <== levelHashes[i];
mux[i].s <== path_index[i];
hashers[i].left <== mux[i].out[0];
hashers[i].right <== mux[i].out[1];
levelHashes[i + 1] <== hashers[i].hash;
}
root <== levelHashes[n_levels];
}

View File

@ -0,0 +1,143 @@
pragma circom 2.0.0;
include "./incrementalMerkleTree.circom";
include "../node_modules/circomlib/circuits/poseidon.circom";
template HasherAB() {
signal input a;
signal input b;
signal output out;
component hasher = Poseidon(2);
hasher.inputs[0] <== a;
hasher.inputs[1] <== b;
out <== hasher.out;
}
template CalculateIdentityCommitment() {
signal input secret;
signal output out;
component hasher = Poseidon(1);
hasher.inputs[0] <== secret;
out <== hasher.out;
}
template CalculateA0(limit) {
signal input identity_secret[limit];
signal output out;
component hasher = Poseidon(limit);
var i;
for(i=0;i<limit;i++) {
hasher.inputs[i] <== identity_secret[i];
}
out <== hasher.out;
}
template CalculateOutput(limit) {
signal input a0;
signal input identity_secret[limit];
signal input epoch;
signal input x;
signal input rln_identifier;
signal output out;
signal output nullifier;
signal degrees[limit];
signal values[limit];
component coeffs[limit];
component nullifierHash = Poseidon(limit + 1);
degrees[0] <== x;
coeffs[0] = HasherAB();
coeffs[0].a <== identity_secret[0];
coeffs[0].b <== epoch;
values[0] <== coeffs[0].out * degrees[0] + a0;
nullifierHash.inputs[0] <== coeffs[0].out;
var i;
for(i = 1; i < limit; i++) {
degrees[i] <== x * degrees[i - 1];
coeffs[i] = HasherAB();
coeffs[i].a <== identity_secret[i];
coeffs[i].b <== epoch;
values[i] <== coeffs[i].out * degrees[i] + values[i - 1];
nullifierHash.inputs[i] <== coeffs[i].out;
}
component rln_identifier_hash = Poseidon(1);
rln_identifier_hash.inputs[0] <== rln_identifier;
nullifierHash.inputs[limit] <== rln_identifier_hash.out;
out <== values[limit-1];
nullifier <== nullifierHash.out;
}
template NRLN(n_levels, limit) {
//constants
var LEAVES_PER_NODE = 2;
var LEAVES_PER_PATH_LEVEL = LEAVES_PER_NODE - 1;
//private signals
signal input identity_secret[limit];
signal input path_elements[n_levels][LEAVES_PER_PATH_LEVEL];
signal input identity_path_index[n_levels];
//public signals
signal input x; // x is actually just the signal hash
signal input epoch;
signal input rln_identifier;
//outputs
signal output y;
signal output root;
signal output nullifier;
var i;
var j;
component A0 = CalculateA0(limit);
for(i = 0; i < limit; i++) {
A0.identity_secret[i] <== identity_secret[i];
}
component identity_commitment = CalculateIdentityCommitment();
identity_commitment.secret <== A0.out;
component inclusionProof = MerkleTreeInclusionProof(n_levels);
inclusionProof.leaf <== identity_commitment.out;
for (i = 0; i < n_levels; i++) {
for (j = 0; j < LEAVES_PER_PATH_LEVEL; j++) {
inclusionProof.path_elements[i][j] <== path_elements[i][j];
}
inclusionProof.path_index[i] <== identity_path_index[i];
}
root <== inclusionProof.root;
component PX = CalculateOutput(limit);
for (i = 0; i < limit; i++) {
PX.identity_secret[i] <== identity_secret[i];
}
PX.epoch <== epoch;
PX.a0 <== A0.out;
PX.x <== x;
PX.rln_identifier <== rln_identifier;
y <== PX.out;
nullifier <== PX.nullifier;
}

View File

@ -0,0 +1,5 @@
pragma circom 2.0.0;
include "./nrln-base.circom";
component main {public [x, epoch, rln_identifier ]} = NRLN(15, 2);

View File

@ -0,0 +1,95 @@
pragma circom 2.0.0;
include "./incrementalMerkleTree.circom";
include "../node_modules/circomlib/circuits/poseidon.circom";
template CalculateIdentityCommitment() {
signal input identity_secret;
signal output out;
component hasher = Poseidon(1);
hasher.inputs[0] <== identity_secret;
out <== hasher.out;
}
template CalculateA1() {
signal input a_0;
signal input epoch;
signal output out;
component hasher = Poseidon(2);
hasher.inputs[0] <== a_0;
hasher.inputs[1] <== epoch;
out <== hasher.out;
}
template CalculateNullifier() {
signal input a_1;
signal input rln_identifier;
signal output out;
component hasher = Poseidon(2);
hasher.inputs[0] <== a_1;
hasher.inputs[1] <== rln_identifier;
out <== hasher.out;
}
template RLN(n_levels) {
//constants
var LEAVES_PER_NODE = 2;
var LEAVES_PER_PATH_LEVEL = LEAVES_PER_NODE - 1;
//private signals
signal input identity_secret;
signal input path_elements[n_levels][LEAVES_PER_PATH_LEVEL];
signal input identity_path_index[n_levels];
//public signals
signal input x; // x is actually just the signal hash
signal input epoch;
signal input rln_identifier;
//outputs
signal output y;
signal output root;
signal output nullifier;
component identity_commitment = CalculateIdentityCommitment();
identity_commitment.identity_secret <== identity_secret;
var i;
var j;
component inclusionProof = MerkleTreeInclusionProof(n_levels);
inclusionProof.leaf <== identity_commitment.out;
for (i = 0; i < n_levels; i++) {
for (j = 0; j < LEAVES_PER_PATH_LEVEL; j++) {
inclusionProof.path_elements[i][j] <== path_elements[i][j];
}
inclusionProof.path_index[i] <== identity_path_index[i];
}
root <== inclusionProof.root;
// 2. Part
// Line Equation Constaints
// a_1 = hash(a_0, epoch)
// share_y == a_0 + a_1 * share_x
component a_1 = CalculateA1();
a_1.a_0 <== identity_secret;
a_1.epoch <== epoch;
y <== identity_secret + a_1.out * x;
component calculateNullifier = CalculateNullifier();
calculateNullifier.a_1 <== a_1.out;
calculateNullifier.rln_identifier <== rln_identifier;
nullifier <== calculateNullifier.out;
}

View File

@ -0,0 +1,5 @@
pragma circom 2.0.0;
include "./rln-base.circom";
component main {public [x, epoch, rln_identifier ]} = RLN(15);

Binary file not shown.