mirror of https://github.com/vacp2p/research.git
add rln
This commit is contained in:
parent
4638ac51d8
commit
49893de561
|
@ -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
|
||||
|
@ -9,4 +9,4 @@ mkdir -p $CIRCOM_BASE/$1/keys
|
|||
mkdir -p $CIRCOM_BASE/$1/proofs
|
||||
cp $CIRCOM_BASE/template/Makefile.tmpl $CIRCOM_BASE/$1/Makefile
|
||||
cp $CIRCOM_BASE/template/main.circom.tmpl $CIRCOM_BASE/$1/src/$DEFAULT_FILENAME.circom
|
||||
cp $CIRCOM_BASE/template/input.json.tmpl $CIRCOM_BASE/$1/input.json
|
||||
cp $CIRCOM_BASE/template/input.json.tmpl $CIRCOM_BASE/$1/input.json
|
||||
|
|
|
@ -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
|
|
@ -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"
|
||||
}
|
|
@ -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];
|
||||
}
|
|
@ -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;
|
||||
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
pragma circom 2.0.0;
|
||||
|
||||
include "./nrln-base.circom";
|
||||
|
||||
component main {public [x, epoch, rln_identifier ]} = NRLN(15, 2);
|
|
@ -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;
|
||||
}
|
|
@ -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.
Loading…
Reference in New Issue