# [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