# [ETH Taipei] Unirep workshop ## Github - https://github.com/unirep/create-unirep-app ## CLI ```shell npx create-unirep-app ``` ```shell yarn build yarn start ``` ## post ```solidity! event Post(uint256 indexed epochKey, uint256 content); function post( // epoch key uint256[] memory publicSignals, uint256[8] memory proof, uint256 content ) public{ unirep.verifyEpochKeyProof(publicSignals, proof); Unirep.EpochKeySignals memory signals = unirep.decodeEpochKeySignals(publicSignals); emit Post(signals.epochKey, content); } ``` ## post test ```typescript! it('post', async() => { const userState = await genUserState(id, app) const {publicSignals, proof} = await userState.genEpochKeyProof() const content = 123 await app.post(publicSignals, proof, content).then(t=>t.wait()) }) ``` ## vote ```solidity! function vote( uint256 epochKey, uint256 upvote, uint256 downvote, // epoch key uint256[] memory publicSignals, uint256[8] memory proof ) public { unirep.verifyEpochKeyProof(publicSignals, proof); Unirep.EpochKeySignals memory signals = unirep.decodeEpochKeySignals(publicSignals); uint fieldIndex = upvote > 0 ? 0 : 1; uint val = upvote > 0 ? upvote : downvote; unirep.attest( epochKey, uint48(signals.epoch), fieldIndex, val ); } ``` ## vote-test ```typescript! it('vote', async() => { const userState = await genUserState(id, app) const upvote = 3 const downvote = 0 const {publicSignals, proof} = await userState.genEpochKeyProof({nonce: 1, revealNonce: true}) await app.vote(epk, upvote, downvote, publicSignals, proof).then(t=>t.wait()) }) ``` ## circuit ``` pragma circom 2.0.0; include "../../../node_modules/@unirep/circuits/circuits/epochKey.circom"; include "../../../node_modules/@unirep/circuits/circuits/circomlib/circuits/comparators.circom"; template NotEpochKey(STATE_TREE_DEPTH, EPOCH_KEY_NONCE_PER_EPOCH, FIELD_COUNT) { // Global state tree signal input state_tree_indexes[STATE_TREE_DEPTH]; signal input state_tree_elements[STATE_TREE_DEPTH]; // Global state tree leaf: Identity & user state root signal input identity_secret; signal output epoch_key; signal output state_tree_root; signal input reveal_nonce; signal input attester_id; signal input epoch; signal input nonce; signal input data[FIELD_COUNT]; // Some arbitrary data to endorse signal input sig_data; signal input not_epoch_key; // the identity_secret doesn't own this key signal output control; // extend epoch key proof component epochKey = EpochKey(STATE_TREE_DEPTH, EPOCH_KEY_NONCE_PER_EPOCH, FIELD_COUNT); for(var i = 0; i < STATE_TREE_DEPTH; i++) { epochKey.state_tree_indexes[i] <== state_tree_indexes[i]; epochKey.state_tree_elements[i] <== state_tree_elements[i]; } epochKey.identity_secret <== identity_secret; epochKey.reveal_nonce <== reveal_nonce; epochKey.attester_id <== attester_id; epochKey.epoch <== epoch; epochKey.nonce <== nonce; for(var i = 0; i < FIELD_COUNT; i++) { epochKey.data[i] <== data[i]; } epochKey.sig_data <== sig_data; control <== epochKey.control; epoch_key <== epochKey.epoch_key; state_tree_root <== epochKey.state_tree_root; component epoch_key_hashers[EPOCH_KEY_NONCE_PER_EPOCH]; component is_equals[EPOCH_KEY_NONCE_PER_EPOCH]; for(var i = 0; i < EPOCH_KEY_NONCE_PER_EPOCH; i++ ){ epoch_key_hashers[i] = Poseidon(4); epoch_key_hashers[i].inputs[0] <== identity_secret; epoch_key_hashers[i].inputs[1] <== attester_id; epoch_key_hashers[i].inputs[2] <== epoch; epoch_key_hashers[i].inputs[3] <== i; is_equals[i] = IsEqual(); is_equals[i].in[0] <== epoch_key_hashers[i].out; is_equals[i].in[1] <== not_epoch_key; is_equals[i].out === 0; } } ``` ## circuilt cli ``` cd packages/circuits && yarn buildsnark ``` ## telegram group https://t.me/+qc2_ppTWgc84Njg9