# Mining Flow in the back-end

Users connect their wallets on the [INTMAX website](https://app.intmax.io/). Initially, they sign with the connected wallet to generate the INTMAX address they will use. Once the INTMAX address is generated, they can start mining.

The INTMAX website provides features to simplify complex address management for mining. Users only need to visit the website and perform the required actions when making deposits or withdrawals.

**IMPORTANT**: It is essential to keep the deposit and withdrawal addresses separate. It is recommended to use the UI, which will guide you to automatically manage multiple addresses.

### The History of This Mining <a href="#id-9-the-history-of-this-mining" id="id-9-the-history-of-this-mining"></a>

* **June 8, 2024**: Mining begins
* **September 5, 2024**: Mining page pinned
* **September 14, 2024**: The ERC20 contract is deployed by LappsNet in El Salvador
* **September 28, 2024**: Deposit contract upgraded
* **October 19, 2024**: Migration to Base Mainnet
* **Q2 2025**: Migration to Ethereum Mainnet; old CLI-based mining was discontinued

{% hint style="warning" %}
**NOTE**: Access from heavily regulated regions such as the United States may be partially blocked. Please use the service at your own risk, adhering to all local laws and regulations.
{% endhint %}

***

### APPENDIX: DETAILS OF REWARD CLAIMING <a href="#id-10-appendix-details-of-reward-claiming" id="id-10-appendix-details-of-reward-claiming"></a>

### Overview of Privacy Mining and Claim <a href="#id-101-overview-of-privacy-mining-and-claim" id="id-101-overview-of-privacy-mining-and-claim"></a>

Privacy Mining allows users to deposit tokens into the system, lock them for a certain period (determined by a ZKP circuit), and later claim their rewards. Claims require users to produce zero-knowledge proofs to demonstrate:

* A valid deposit has been made.
* A sufficient lock period has elapsed since the deposit.
* The deposit address has not sent any transfers during the lock period.
* The deposit has not been double-spent (double-claim prevention).

These claims are aggregated into a single proof for on-chain verification, ultimately enabling reward distribution to recipients on Ethereum.

### Privacy Mining Flow <a href="#id-102-privacy-mining-flow" id="id-102-privacy-mining-flow"></a>

The high-level flow of Privacy Mining related to claiming rewards is as follows:

1. **Fetch your ongoing mining**
   * Obtains a **Mining** record (an object) that includes information such as deposit details, the block in which the deposit was included, the maturity time, etc.
   * A mining record has the following structure:
     * `deposit_data`: Detailed information about the deposit, including `deposit_salt`.
     * `block`: The first block that contains the deposit.
     * `maturity`: The maturity Unix timestamp.
     * `status`: Current status of the deposit, possible values include:

       * `locked`: Deposit is currently locked.
       * `claimable`: Deposit has matured and is ready to be claimed.
       * `claimed`: Deposit has already been claimed.

2. **Check If a Mining Is Already Claimed**

   * Before creating a new claim, the system confirms if any deposit (identified by a deposit index or nullifier) has already been claimed.

3. **Determine the Correct Claim Block**

   * Let `deposit_block_number` be the block number in which the deposit was first included.
   * Let `claim_block_number` be a block number after the deposit’s lock period has passed.
   * **Constraint**: No other token transfers from the same public key are allowed between `deposit_block_number` and `claim_block_number`.

4. **Wait for Validity Prover Synchronization**

   * The system’s validity prover must be synced up to the `claim_block_number`.

5. **Obtain Update Proof**

   * Update the balance proof from `deposit_block_number` to `claim_block_number`, creating an update witness (sometimes called an **UpdateWitness**).

6. **Compute Merkle Trees at Relevant Blocks**

   * For the block at `deposit_block_number` and the immediately preceding block, compute the Merkle proofs for the deposit index.
   * These proofs show that the deposit was included at `deposit_block_number` and *not* included in the previous block, thus identifying the exact block where the deposit became valid.

7. **Construct the `DepositTimeWitness`**
   * Combine the Merkle proofs and block data into a structure called **DepositTimeWitness**.
   * `DepositTimeWitnes` has the following structure:

     * `publicWitness`:
       * `prevBlock`: The previous Intmax block before the user's deposit.
       * `block`: The Intmax block containing the user's deposit.
       * `depositMerkleProof`: A Merkle proof demonstrating that the user's deposit is included in the deposit tree at the time of `currentBlock`.
       * `prevDepositMerkleProof`: A Merkle proof demonstrating that the user's deposit was **not** included in the deposit tree at the previous block (`prevBlock`).
     * `depositIndex`: The index of the user's deposit within the deposit tree.
     * `deposit`: The publicly available details of the user's deposit.
     * `depositSalt`: A value used for computing the recipient salt hash.
     * `pubkey`: The user’s public key.

8. **Combine to Form the `ClaimWitness`**
   * Package the deposit-time information, the update proof, and the final claim recipient into a single structure called **ClaimWitness**:

     * `recipient`: the user’s address to receive mining rewards.
     * `depositTimeWitness`
     * `updateWitness`

9. **Generate the Single Claim Proof**

   * The user runs:
     1. `DepositTimeCircuit`:
     2. `SingleClaimCircuit`:
   * These produce a **single\_claim\_proof**, which is a Plonky2 proof verifying deposit validity, maturity, and up-to-date balance status.

10. **Claim Aggregation**

    * A “claim aggregator” then takes multiple `single_claim_proof`s and merges them with a previously aggregated claim proof (`prev_claim_proof`) into a single “cyclic” proof. This repeated aggregation yields one final proof (`claim_proof`) verifying multiple claims at once.

11. **Wrapping Proof for On-Chain Verification**

    * The aggregator wraps the `claim_proof` into a format suitable for gnark-based Solidity verification. This wrapped proof is returned as a `wrapped_claim_proof`.

12. **On-Chain Submission**

    * The aggregator (or user) calls `submitClaimProof` on-chain, providing the `wrapped_claim_proof`.
    * The smart contract verifies all claims within that proof, storing any new or unprocessed claims in contract storage.

13. **Daily Aggregation and Reward Assignment**

    * Claims are aggregated daily, with the reward distribution schedule set to **every day at 00:00 UTC**.

14. **Relay of Claims to Ethereum**
    * By calling `relayClaim(period)`, the aggregator or a relayer informs Ethereum about the claims.
    * Then a relayer calls `relayMessageWithProof`, causing the reward tokens (ITX) to be sent to the user’s recipient address.
    * Internally, `relayMessageWithProof` calls the liquidity contract’s `processWithdrawals`, finalizing the transfer.

### Claim Contract Specification <a href="#id-103-claim-contract-specification" id="id-103-claim-contract-specification"></a>

#### Claim Structure <a href="#id-1031-claim-structure" id="id-1031-claim-structure"></a>

```
{
    "recipient": "0xabc...def",
    "amount": 1000000000000000000,
    "nullifier": "0xabc...def",
    "block_hash": "0xabc...def",
    "block_number": 12
}
```

* **recipient**: The recipient of the claim
* **amount**: The amount of the deposit (in wei)
* **nullifier**: Used to prevent double claims
* **block\_hash**: Balance proof block hash used for withdrawal
* **block\_number**: Balance proof block number used for withdrawal

#### Claim Aggregation Flow <a href="#id-1032-claim-aggregation-flow" id="id-1032-claim-aggregation-flow"></a>

1. **Single Claim Proof**
   * The user obtains a proof (e.g., `ProofWithPublicInputs`) from the `SingleClaimCircuit`.
2. **Aggregation**
   * The aggregator repeatedly merges:

     ```
     prev_claim_proof + single_claim_proof → claim_proof
     ```
   * This creates a single cyclic proof containing multiple claims.
3. **Wrapping for gnark**
   * The aggregator or server creates a “wrapped” proof compatible with gnark, enabling a Solidity contract to finalize on-chain verification.

#### Contract Functions <a href="#id-1033-contract-functions" id="id-1033-contract-functions"></a>

* **`submitClaimProof`**
  * Accepts the aggregated `wrapped_claim_proof` on-chain.
  * In the on-chain verification process, the `block_number` and `block_hash` referenced by each Claim must match the latest data from the Rollup, verified by calling something like `IRollup.getBlockHash(block_number)`.
  * The smart contract manages daily reward allocations using an allocation mechanism (e.g., `AllocationLib`). When executing the `relayClaims` function, processing is performed based on this allocation data.
* **`relayClaim`**
  * Communicates the final reward data to the Ethereum contract, referencing a specific `period`.
* **`relayMessageWithProof`**
  * Called by a relayer after `relayClaim`, finalizing the token transfer by calling a liquidity contract’s `processWithdrawals`.

### Claim ZKP Constraints and Circuits <a href="#id-104-claim-zkp-constraints-and-circuits" id="id-104-claim-zkp-constraints-and-circuits"></a>

The Claim ZKP is composed of two main sub-circuits:

1. **DepositTimeCircuit** is a ZKP circuit that verifies a deposit was included for the first time in a specific block and that a valid lock duration was set.
2. **SingleClaimCircuit** verifies that the deposit has matured and that no other transfers occurred from the user's account during the lock period.

#### DetermineLockTimeTarget <a href="#id-1041-determinelocktimetarget" id="id-1041-determinelocktimetarget"></a>

`DetermineLockTimeTarget` is an intermediate module for computing the lock time.

The lock time is derived from the deposit’s block hash and salt:

* **block\_hash**: 32 bytes
* **deposit\_salt**: Some Salt type

**Pseudo-steps**:

1. `seed_poseidon` = PoseidonHash(block\_hash, deposit\_salt)
2. Convert `seed_poseidon` into a value within `[172800, 432000]` (2–5 days in seconds).

#### DepositTimeTarget <a href="#id-1042-deposittimetarget" id="id-1042-deposittimetarget"></a>

`DepositTimeTarget` ensures:

1. **Block Linking**
   * `prev_block` and `block` are valid blocks.
   * `prev_block.block_hash` equals `block.prev_block_hash`.
2. **Deposit Validity**
   * `deposit.is_eligible` is `true`.
   * `deposit_index` fits within 32 bits.
   * `deposit_salt` is valid.
   * `pubkey` is 256 bits.
3. **Merkle Proof Checks**
   * A proof that at `deposit_index`, the deposit was *not* included in `prev_block`.
   * A proof that at the same `deposit_index`, the deposit *is* included in `block`.
4. **Salt Hash Matching**
   * `pubkey_salt_hash` is computed from `deposit` and `deposit_salt`.
   * `Poseidon(deposit, deposit_salt)` produces a `nullifier` for double-claim prevention.
5. **Lock Time Reference**
   * Checks that `determine_lock_time_target.block_hash` and `deposit_salt` match the deposit data.

#### DepositTimeCircuit <a href="#id-1043-deposittimecircuit" id="id-1043-deposittimecircuit"></a>

* Enforces all constraints from `DepositTimeTarget`.
* Exposes the necessary public inputs (`block_number`, `block_hash`, `pubkey`, etc.) for the subsequent circuit to verify deposit-time correctness.

#### SingleClaimTarget <a href="#id-1044-singleclaimtarget" id="id-1044-singleclaimtarget"></a>

Within the `SingleClaimCircuit`, we have constraints such as:

1. **Valid Plonky2 Proofs**: Both `validity_proof` and `deposit_time_proof` must be valid.
2. **Merkle Proofs**: The `block_merkle_proof` confirms `block_hash` is indeed part of a recognized `block_tree_root`.
3. **Account Membership Proof**: Ensures no transaction was sent by this pubkey prior to the relevant block.
4. **Maturity Check**: Confirms the deposit is matured by checking `deposit_time + lock_time <= current_block_timestamp`.
5. **Recipient Format**: The `recipient` must be a valid address.

#### SingleClaimCircuit <a href="#id-1045-singleclaimcircuit" id="id-1045-singleclaimcircuit"></a>

* Uses a zero-knowledge configuration (Plonky2).
* Enforces the constraints from **SingleClaimTarget**.
* The public inputs follow the structure described in **3.1 Claim Structure**.

### Putting It All Together <a href="#id-105-putting-it-all-together" id="id-105-putting-it-all-together"></a>

1. The user performs a deposit, creating a **Mining** record.
2. Once the deposit’s lock time is reached, the user initiates a **claim**.
3. The system checks if the deposit is unclaimed and constructs:

   * DepositTimeWitness
   * UpdateWitness

   These form a **ClaimWitness**.
4. The user or aggregator runs:
   * **DepositTimeCircuit** checks that a deposit was included for the first time in a specific block and that a valid lock duration was set.
   * **SingleClaimCircuit** checks that the deposit has matured and that no other transfers occurred from the user's account during the lock period.
5. A single proof (`single_claim_proof`) is produced.
6. Multiple single claims can be aggregated into one (`claim_proof`).
7. The proof is wrapped for gnark-based Solidity verification.
8. On-chain:
   * **submitClaimProof** is invoked, verifying all claims and storing new claim info.
   * Rewards are aggregated daily, with final distribution triggered via:
     * **relayClaim** → signals to Ethereum.
     * **relayMessageWithProof** → calls `processWithdrawals` for ITX token distribution.

#### Final Notes <a href="#final-notes" id="final-notes"></a>

* Randomizing the lock time is crucial to avoid predictable deposit intervals.
* The `nullifier` prevents double-spending/claiming.
* Aggregating claims into a single proof significantly reduces on-chain verification costs.
* All core data (block hashes, Merkle proofs, account membership) must be validated by the circuit to ensure system integrity and privacy.


---

# Agent Instructions: 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://intmax-general.gitbook.io/intmax-privacy-mining/getting-started/privacy-mining-overview/mining-flow-in-the-back-end.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.
