Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
cc8acc8
remove unused param
r06922097 Jan 21, 2021
71e6f99
update from the original repo
r06922097 Mar 1, 2021
59f6b5c
optional -mp, -mn, -md, -gp to prove
vivianjeng Mar 2, 2021
a7d808d
Merge branch 'master' of https://github.com/NIC619/UniRep
vivianjeng Mar 2, 2021
b4bbb3b
update verifyReputation and Unirep.sol to prove -md
vivianjeng Mar 3, 2021
9fd29ac
upvote downvote cli
vivianjeng Mar 4, 2021
5551a81
Merge remote-tracking branch 'upstream/master'
vivianjeng Mar 4, 2021
ae90ab0
post and comment on smart contract
vivianjeng Mar 5, 2021
00b6e44
leaveComment, publishPost, listAllPost functions
vivianjeng Mar 8, 2021
ade2c63
mongoose: post
vivianjeng Mar 15, 2021
e9e6f71
mongoose: comment
vivianjeng Mar 16, 2021
411fe3e
add Schemas
vivianjeng Mar 24, 2021
69070ea
submit karma nullifiers while upvote/downvote/post/comment
vivianjeng Apr 13, 2021
e59b9a8
hasedLeaf = hash5(idCommitment, stateRoot, posRep, negRep, 0)
vivianjeng Apr 14, 2021
bc4bc9b
prove reputation from attester
vivianjeng Apr 14, 2021
f69a27c
prove reputation from attester
vivianjeng Apr 14, 2021
57363c6
add event schema, reputationFromAttesterVerifier
vivianjeng Apr 16, 2021
294f3ff
gen proving circuit from db, db utils
vivianjeng Apr 26, 2021
34035e4
change default GST leaf, modify integration test
vivianjeng Apr 28, 2021
1cf0652
add db flag, remove unused schema
vivianjeng Apr 29, 2021
5bcddbc
verifyReputationProof, add Mux1 circuit
vivianjeng Apr 30, 2021
e1b2d19
resume gen epoch key and proof
vivianjeng May 2, 2021
396a033
fix test scripts
vivianjeng May 5, 2021
941e011
update new_rep by adding old_rep
vivianjeng May 12, 2021
8ddef4a
test post function
vivianjeng May 13, 2021
e777f07
test vote function
vivianjeng May 14, 2021
f5cc08c
remove unused parameters
vivianjeng May 16, 2021
115e985
trigger GitHub actions
vivianjeng May 19, 2021
006b35c
create a branch with database functions
vivianjeng May 20, 2021
8d2da47
Merge remote-tracking branch 'upstream/master'
vivianjeng May 20, 2021
140fe7a
update README.MD
vivianjeng May 21, 2021
102c417
Merge branch 'master' of https://github.com/NIC619/UniRep
vivianjeng May 24, 2021
6c3bb72
remove mongoose dependencies
vivianjeng May 25, 2021
c3dcb60
update README.md
vivianjeng Jun 2, 2021
b465db3
Apply suggestions from code review
vivianjeng Jun 7, 2021
d2b7f73
Apply suggestions from code review, apply DeprecationWarning
vivianjeng Jun 8, 2021
1fff4c7
Trigger CI
vivianjeng Jun 8, 2021
9eefd8c
Update node.js.yml
vivianjeng Jun 8, 2021
0585dfe
seperate Unirep Social from Unirep
vivianjeng Jun 16, 2021
e25c0c2
update EventSequencing test, fix reused `i` in loop
vivianjeng Jun 17, 2021
49347d0
update test script
vivianjeng Jun 21, 2021
8a01445
use `unirepSocialContract` in cli tests
vivianjeng Jul 22, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .DS_Store
Binary file not shown.
6 changes: 1 addition & 5 deletions .github/workflows/node.js.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,7 @@

name: Node.js CI

on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
on: [push, pull_request]

jobs:
build:
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
node_modules
.DS_Store

#Buidler files
cache
Expand All @@ -8,4 +9,5 @@ build
#Verifier solidity contracts
EpochKeyValidityVerifier.sol
ReputationVerifier.sol
ReputationFromAttesterVerifier.sol
UserStateTransitionVerifier.sol
230 changes: 7 additions & 223 deletions README.MD

Large diffs are not rendered by default.

7 changes: 3 additions & 4 deletions circuits/processAttestations.circom
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ include "./hasherPoseidon.circom";
include "./sparseMerkleTree.circom";
include "./verifyHashChain.circom";

template ProcessAttestations(nullifier_tree_depth, user_state_tree_depth, NUM_ATTESTATIONS) {
template ProcessAttestations(user_state_tree_depth, NUM_ATTESTATIONS) {
signal input epoch;
signal input nonce;
signal input identity_nullifier;
Expand Down Expand Up @@ -92,7 +92,6 @@ template ProcessAttestations(nullifier_tree_depth, user_state_tree_depth, NUM_AT
epoch_key_nullifier <== epoch_key_nullifier_hasher.hash;
/* End of 1. verify attestation hash chain and compute nullifiers */


/* 2. Process attestations and update user state tree */

// If the attestation is not to be processed, we check and verify leaf 0 instead.
Expand Down Expand Up @@ -157,8 +156,8 @@ template ProcessAttestations(nullifier_tree_depth, user_state_tree_depth, NUM_AT
overwrite_graffiti_muxer[i].c[1] <== graffities[i];
overwrite_graffiti_muxer[i].s <== overwrite_graffitis[i];
new_leaf_value_hasher[i] = Hasher5();
new_leaf_value_hasher[i].in[0] <== pos_reps[i];
new_leaf_value_hasher[i].in[1] <== neg_reps[i];
new_leaf_value_hasher[i].in[0] <== pos_reps[i] + old_pos_reps[i];
new_leaf_value_hasher[i].in[1] <== neg_reps[i] + old_neg_reps[i];
new_leaf_value_hasher[i].in[2] <== overwrite_graffiti_muxer[i].out;
new_leaf_value_hasher[i].in[3] <== 0;
new_leaf_value_hasher[i].in[4] <== 0;
Expand Down
184 changes: 111 additions & 73 deletions circuits/proveReputation.circom
Original file line number Diff line number Diff line change
@@ -1,41 +1,51 @@
include "../node_modules/circomlib/circuits/comparators.circom";
include "../node_modules/circomlib/circuits/mux1.circom";
include "./hasherPoseidon.circom";
include "./identityCommitment.circom";
include "./incrementalMerkleTree.circom";
include "./modulo.circom";
include "./sparseMerkleTree.circom";

template ProveReputation(GST_tree_depth, user_state_tree_depth, nullifier_tree_depth, EPOCH_KEY_NONCE_PER_EPOCH) {
include "./userExists.circom";
include "./verifiyEpochKey.circom";

template ProveReputation(
GST_tree_depth,
nullifier_tree_depth,
epoch_tree_depth,
EPOCH_KEY_NONCE_PER_EPOCH,
MAX_REPUTATION_SCORE_BITS,
MAX_KARMA_BUDGET) {
signal input epoch;
signal private input nonce;

// Global state tree leaf: Identity & user state root
signal private input identity_pk[2];
signal private input identity_nullifier;
signal private input identity_trapdoor;
signal private input user_state_root;
signal private input user_tree_root;
signal private input user_state_hash;
// Generate epoch key from epoch_key_nonce
signal private input epoch_key_nonce;
signal input epoch_key;
// Global state tree
signal private input GST_path_index[GST_tree_depth];
signal private input GST_path_elements[GST_tree_depth][1];
signal input GST_root;
// Nullifier tree
signal input nullifier_tree_root
signal private input nullifier_path_elements[nullifier_tree_depth][1];
// Attester to prove reputation from
signal input attester_id;
// Attestation by the attester
signal private input pos_rep;
signal private input neg_rep;
signal private input graffiti;
signal private input UST_path_elements[user_state_tree_depth][1];
// Condition on repuations to prove
signal input min_pos_rep;
signal input max_neg_rep;
// Graffiti
signal input graffiti_pre_image;

var MAX_REPUTATION_SCORE_BITS = 252;

// Sum of positive and negative karma
signal private input positive_karma;
signal private input negative_karma;
// Karma nullifier
signal private input selectors[MAX_KARMA_BUDGET];
signal input prove_karma_nullifiers;
signal input prove_karma_amount;
signal private input karma_nonce[MAX_KARMA_BUDGET];
signal output karma_nullifiers[MAX_KARMA_BUDGET];
// Prove the minimum reputation
signal input prove_min_rep;
signal input min_rep;

/* 1. Check nonce validity */
var bitsPerNonce = 8;
Expand All @@ -46,55 +56,38 @@ template ProveReputation(GST_tree_depth, user_state_tree_depth, nullifier_tree_d
nonce_lt.out === 1;
/* End of check 1 */

/* 2. Check if user exists in the Global State Tree */
component identity_commitment = IdentityCommitment();
identity_commitment.identity_pk[0] <== identity_pk[0];
identity_commitment.identity_pk[1] <== identity_pk[1];
identity_commitment.identity_nullifier <== identity_nullifier;
identity_commitment.identity_trapdoor <== identity_trapdoor;

component leaf = HashLeftRight();
leaf.left <== identity_commitment.out;
leaf.right <== user_state_root;

component GST_leaf_exists = LeafExists(GST_tree_depth);
GST_leaf_exists.leaf <== leaf.hash;
for (var i = 0; i < GST_tree_depth; i++) {
GST_leaf_exists.path_index[i] <== GST_path_index[i];
GST_leaf_exists.path_elements[i][0] <== GST_path_elements[i][0];
}
GST_leaf_exists.root <== GST_root;
/* End of check 2 */


/* 3. Check if the reputation given by the attester is in the user state tree */
component reputation_hasher = Hasher5();
reputation_hasher.in[0] <== pos_rep;
reputation_hasher.in[1] <== neg_rep;
reputation_hasher.in[2] <== graffiti;
reputation_hasher.in[3] <== 0;
reputation_hasher.in[4] <== 0;

component reputation_membership_check = SMTLeafExists(user_state_tree_depth);
reputation_membership_check.leaf_index <== attester_id;
reputation_membership_check.leaf <== reputation_hasher.hash;
for (var i = 0; i < user_state_tree_depth; i++) {
reputation_membership_check.path_elements[i][0] <== UST_path_elements[i][0];
/* 2. Check if user exists in GST and check correctness of epoch key */
component verify_epoch_key = verifyEpochKey(GST_tree_depth, epoch_tree_depth, EPOCH_KEY_NONCE_PER_EPOCH);
for (var i = 0; i< GST_tree_depth; i++) {
verify_epoch_key.GST_path_index[i] <== GST_path_index[i];
verify_epoch_key.GST_path_elements[i][0] <== GST_path_elements[i][0];
}
reputation_membership_check.root <== user_state_root;
/* End of check 3 */
verify_epoch_key.GST_root <== GST_root;
verify_epoch_key.identity_pk[0] <== identity_pk[0];
verify_epoch_key.identity_pk[1] <== identity_pk[1];
verify_epoch_key.identity_nullifier <== identity_nullifier;
verify_epoch_key.identity_trapdoor <== identity_trapdoor;
verify_epoch_key.user_tree_root <== user_tree_root;
verify_epoch_key.user_state_hash <== user_state_hash;
verify_epoch_key.positive_karma <== positive_karma;
verify_epoch_key.negative_karma <== negative_karma;
verify_epoch_key.nonce <== epoch_key_nonce;
verify_epoch_key.epoch <== epoch;
verify_epoch_key.epoch_key <== epoch_key;
/* End of check 2 */


/* 4. Check it's latest epoch the user transition to */
/* 3. Check it's latest epoch the user transition to */
// We check that nullifier of the epoch key is not seen before.
// 4.1.1 Compute nullifier of the epoch key
// 3.1.1 Compute nullifier of the epoch key
component epoch_key_nullifier_hasher = Hasher5();
epoch_key_nullifier_hasher.in[0] <== 2; // 2 is the domain separator for epoch key nullifier
epoch_key_nullifier_hasher.in[1] <== identity_nullifier;
epoch_key_nullifier_hasher.in[2] <== epoch;
epoch_key_nullifier_hasher.in[3] <== nonce;
epoch_key_nullifier_hasher.in[4] <== 0;
// 4.1.2 Mod nullifier hash
// 3.1.2 Mod nullifier hash
// circom's best practices state that we should avoid using <-- unless
// we know what we are doing. But this is the only way to perform the
// modulo operation.
Expand All @@ -103,7 +96,7 @@ template ProveReputation(GST_tree_depth, user_state_tree_depth, nullifier_tree_d
modEPKNullifier.dividend <== epoch_key_nullifier_hasher.hash;
epk_nullifier_hash_moded <== modEPKNullifier.remainder;

// 4.2 Verify non-membership of the nullifier in nullifier tree
// 3.2 Verify non-membership of the nullifier in nullifier tree
// Unseen nullifier leaf should have value hashLeftRight(0, 0)
signal zero_leaf;
component zero_leaf_hasher = HashLeftRight();
Expand All @@ -118,25 +111,70 @@ template ProveReputation(GST_tree_depth, user_state_tree_depth, nullifier_tree_d
for (var i = 0; i < nullifier_tree_depth; i++) {
epk_exists.path_elements[i][0] <== nullifier_path_elements[i][0];
}
/* End of check 4 */

/* End of check 3 */

/* 5. Check conditions on reputations */
component pos_rep_gt = GreaterThan(MAX_REPUTATION_SCORE_BITS);
pos_rep_gt.in[0] <== pos_rep;
pos_rep_gt.in[1] <== min_pos_rep;
pos_rep_gt.out === 1;

component neg_rep_lt = LessThan(MAX_REPUTATION_SCORE_BITS);
neg_rep_lt.in[0] <== neg_rep;
neg_rep_lt.in[1] <== max_neg_rep;
neg_rep_lt.out === 1;
/* 4. Check total reputation is greater than 0 */
// if user wants to spend karma and prove total_reputation, it requires reputation to be positive
// total_reputation = positive_karma - negative_karma >= 0
component pos_rep_get = GreaterEqThan(MAX_REPUTATION_SCORE_BITS);
pos_rep_get.in[0] <== positive_karma;
pos_rep_get.in[1] <== negative_karma;
pos_rep_get.out === 1;
/* End of check 4*/


/* 5. Check nullifiers are valid */
signal default_nullifier_zero;
component default_nullifier_zero_hasher = Hasher5();
default_nullifier_zero_hasher.in[0] <== 0;
default_nullifier_zero_hasher.in[1] <== 0;
default_nullifier_zero_hasher.in[2] <== 0;
default_nullifier_zero_hasher.in[3] <== 0;
default_nullifier_zero_hasher.in[4] <== 0;
default_nullifier_zero <== default_nullifier_zero_hasher.hash;

component if_check_nullifiers[MAX_KARMA_BUDGET];
component if_output_nullifiers[MAX_KARMA_BUDGET];
component karma_nullifier_hasher[MAX_KARMA_BUDGET];
component nonce_gt[MAX_KARMA_BUDGET];
for(var i = 0; i< MAX_KARMA_BUDGET; i++) {
// 5.1 verify is nonce is valid
// If user wants to generate karma nullifiers, check if positive_karma - negative_karma > karma_nonce
// Eg. if we have 10 karma, we have 0-9 valid nonce
nonce_gt[i] = GreaterThan(MAX_REPUTATION_SCORE_BITS);
nonce_gt[i].in[0] <== positive_karma - negative_karma;
nonce_gt[i].in[1] <== karma_nonce[i];
if_check_nullifiers[i] = Mux1();
if_check_nullifiers[i].c[0] <== 1;
if_check_nullifiers[i].c[1] <== nonce_gt[i].out;
if_check_nullifiers[i].s <== prove_karma_nullifiers;
if_check_nullifiers[i].out === 1;

// 5.2 Use karma_nonce to compute all karma nullifiers
if_output_nullifiers[i] = Mux1();
karma_nullifier_hasher[i] = Hasher5();
karma_nullifier_hasher[i].in[0] <== 3; // 3 is the domain separator for karma nullifier
karma_nullifier_hasher[i].in[1] <== identity_nullifier;
karma_nullifier_hasher[i].in[2] <== epoch;
karma_nullifier_hasher[i].in[3] <== karma_nonce[i];
karma_nullifier_hasher[i].in[4] <== 0;
if_output_nullifiers[i].c[0] <== default_nullifier_zero;
if_output_nullifiers[i].c[1] <== karma_nullifier_hasher[i].hash;
if_output_nullifiers[i].s <== selectors[i];
karma_nullifiers[i] <== if_output_nullifiers[i].out;
}
/* End of check 5 */

/* 6. Check pre-image of graffiti */
component graffiti_hasher = HashLeftRight();
graffiti_hasher.left <== graffiti_pre_image;
graffiti_hasher.right <== 0;
graffiti_hasher.hash === graffiti;

/* 6. Check if user has reputation greater than min_rep */
component if_check_min_rep = Mux1();
component rep_get = GreaterEqThan(MAX_REPUTATION_SCORE_BITS);
rep_get.in[0] <== positive_karma - negative_karma;
rep_get.in[1] <== min_rep;
if_check_min_rep.c[0] <== 1;
if_check_min_rep.c[1] <== rep_get.out;
if_check_min_rep.s <== prove_min_rep;
if_check_min_rep.out === 1;
/* End of check 6 */
}
Loading