> For the complete documentation index, see [llms.txt](https://unirep.gitbook.io/unirep-social/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://unirep.gitbook.io/unirep-social/introduction.md).

# Introduction

## Cryptography primitives

* poseidon hash function
  * `hashLeftRight()`(represented as `hash` hereafter) and `hash5()`
* [semaphore identity](https://github.com/weijiekoh/libsemaphore)
  * `identityCommitment`
    * `identityCommitment` is the hash of user's EdDSA pubkey, `identityNullifier` and `identityTrapdoor`

## Actors in Unirep

* There are users who receive reputation and prove received reputation

1. **User:** users sign up by calling `userSignUp` in Unirep contract

   * user's `identityCommitment` is revealed at this time and it will be recorded in the contract to prevent double signup
   * the identity commitment will not reveal the actual identity of the user but at the same time allow user to prove identity in the cirucit&#x20;

2. **Attester**: there are attesters who give attestations to users and the attestations become the users' reputation
   * attester signs up by calling `attesterSignUp` in Unirep contract
   * attesters would be given `attesterId` by the order they sign up, `attesterId` begins with `1`
   * attester record and attestation record are public and so everyone can see which attester submits which attestation to the Unirep contract

{% hint style="info" %}

#### Won't this reveal who is receiving what attestation from which attester?

* so the receiver of an attestation is not a user's `identityCommitment` but an random value called **`epochKey`**, i.e., attester attests to an `epochKey` instead of an `identityCommitment`
* `epochKey` is computed by&#x20;

```
hash5(identityNullifier, epoch, nonce, 0, 0)
```

* only the user knows his `identityNullifier` so only he knows if he is receiving an attestation, others would see an attestation attesting to a random value
* and in the circuit user can prove that he knows the `epochKey` and can rightfully receive and process the attestations attested to this `epochKey`
  {% endhint %}

{% hint style="info" %}
**Can a user choose not to process certain attestations that are bad for his reputation?**

* No. The attestations to an `epochKey` would be chained together. A hashchain would be formed by the hashes of the attestations.
  * So user can not omit any attestation because the circuit requires each attestation in the hashchain to be processed.
    * if user omits an attestation, then the computed hashchain would not match the one in the Unirep contract

```
hashChainResult = hash(attestation_3, hash(attestation_2, hash(attestation_1, 0)))
```

{% endhint %}

## Data structures in Unirep

### **User state tree**

* a user state tree is a sparse merkle tree with it's leaves storing reputation received from each attester, e.g.,

  * a user state tree leaf = hash of the reputation

  ```
                                user state tree root
                                /                  \
    hash(DEFAULT_REP_HASH, 0xabc...)              hash(0xbcd..., 0xcde...)
           /        \                                      /         \
  [No rep for leaf 0] [leaf 1: 0xabc...]              [leaf 2: 0xbcd...] [leaf 3: 0xcde...]
  ```
* NOTE: `[leaf 1: 0xabc...]` represents the reputation received from attester with `attesterId = 1` and `0xabc...` is the hash of the reputation

### **Global state tree**

* a global state tree is an incremental sparse merkle tree with it's leaves storing users' `identityCommitment`s and `userStateRoot`s, e.g.,
  * a global state tree leaf = `hash(identityCommitment, userStateRoot)`

```
                            global state tree root
                            /                \
        hash(0xabc..., 0xcde...)         hash(0xdef..., DEFAULT_EMPTY_HASH)
               /        \                          /         \
[leaf_0: 0xabc...] [leaf_1: 0xcde...] [leaf_2: 0xdef...] [DEFAULT_EMPTY_HASH]
```

* NOTE: this is an incremental merkle tree so leaves are inserted from left (leaf index 0) to right, one by one, instead of inserted directly into the specified leaf index.
* NOTE: since global state tree leaf is the hash of `identityCommitment` and `userStateRoot`, others will be not be able to tell which user (his `identityCommitment`) inserted his user state into global state tree.

### **Epoch tree**

* an epoch tree is a sparse merkle tree with it's leaves storing hashchain results of each epoch key, e.g.,

  ```
                                epoch tree root
                               /               \
      hash(DEFAULT_EMPTY_HASH, 0x123...)   hash(DEFAULT_EMPTY_HASH, 0x456...)
            /             \                      /                  \
  [DEFAULT_EMPTY_HASH]  [epk_1: 0x123...]    [DEFAULT_EMPTY_HASH]  [epk_3: 0x456...]
  ```

### **Nullifier tree**

* an nullifier tree is a sparse merkle tree with it's leaves storing nullifier of already processed attestations or epoch keys, e.g.,

  ```
                nullifier tree root
              /                     \
      hash(1, 0)                     hash(0, 1)
     /          \                    /         \
  [leaf 0: 1]  [leaf 1: 0]       [leaf_2: 0] [leaf_3: 1]
  ```
* NOTE: leaf 0 of nullifier tree is reserved, it always has value `1`
* NOTE: leaf value `1` means the nullifier represented by the leaf index is processed. In the example above, nullifier `3` is stored in nullifier tree, this nullifier could be a nullifier of an attestation or an epoch key, and it means that the attestation or the epoch key is processed.
* NOTE: nullifiers are used to prevent user from processing an aleady processed attestation or epoch key.
* an attestation includes the following data:

  ```
  struct Attestation {
    // The attester’s ID
    uint256 attesterId;
    // Positive reputation
    uint256 posRep;
    // Negative reputation
    uint256 negRep;
    // A hash of an arbitary string
    uint256 graffiti;
    // Whether or not to overwrite the graffiti in the user’s state
    bool overwriteGraffiti;
  }
  ```
* nullifier of an attestation is computed by `hash5(ATTESTATION_NULLIFIER_DOMAIN, identityNullifier, attesterId, epoch, epochKey)`
  * `ATTESTATION_NULLIFIER_DOMAIN` is used to prevent mixed-up of attestation nullifier and epoch key nullifier
* nullifier of an epoch key is computed by `hash5(EPOCH_KEY_NULLIFIER_DOMAIN, identityNullifier, epoch, nonce, 0)`
  * `EPOCH_KEY_NULLIFIER_DOMAIN` is used to prevent mixed-up of attestation nullifier and epoch key nullifier
* a reputation includes the following data: `posRep, negRep, graffiti`
  * it does not include `attesterId` like an attestation does because reputation is already stored in user state tree with `attesterId` as leaf index

#### Epoch, epoch transition and user state transition

* There is the notion of epoch in Unirep. Every `epochLength` seconds, one epoch ends and next epoch begins.
  * Epoch transition happens when someone calls `beginEpochTransition`
    * in `beginEpochTransition`, all epoch keys attested during this epoch will have their hash chain sealed
      * by 'sealed' it means that the hash chain is hashed again with `1`, e.g., `hash(1, originalHashChain)`
      * if an epoch key received no attestation, it's hash chain would be `hash(1, 0)`
    * After hash chain of the epoch keys are sealed, these epoch keys and their hash chain will be inserted into the epoch tree of this epoch
      * there's one epoch tree for every epoch
    * caller will be compensated for executing the epoch transition
  * There will be a new global state tree for each epoch
    * and user needs to perform user state transition to transition his user state into the latest epoch
      * user performs user state transition by calling `updateUserStateRoot`
      * once the user performed user state transition, his user state will be inserted into the global state tree of the latest epoch
      * so if a user does not perform user state transition during an epoch, his user state will not be in the global state tree of that epoch
* User should perform user state transition before he can prove the latest attestations he received.
  * Also, user should perform user state transition before he can receive any attestations further. Attester can still attest to a user's epoch key in the past epoch but the user will not be able to process the attestation.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://unirep.gitbook.io/unirep-social/introduction.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
