# income-over-v1

observedMonthlyIncome >= minIncome, both in minor units (amount x 100); the income is the average monthly inflow observed on a connected account. Key only: not registered, never committed; requests and commitments use the currency aliases income-over-<currency>-v1. Proven without revealing the attribute, against a
commitment `Poseidon(value, salt)` the issuer recorded in SuperWalletTrustRegistry
(`commitment(credentialId, circuitId)`), and bound to the verifier's nonce.

**Key only: not registered, never committed.** No request names `income-over-v1` and the issuer
commits nothing under its id. Requests and commitments use the currency circuits, which share this
circuit's files, key and verifier contract: [income-over-krw-v1](../income-over-krw-v1/), [income-over-lak-v1](../income-over-lak-v1/), [income-over-vnd-v1](../income-over-vnd-v1/), [income-over-thb-v1](../income-over-thb-v1/), [income-over-kgs-v1](../income-over-kgs-v1/), [income-over-usd-v1](../income-over-usd-v1/).

| | |
|---|---|
| circuitId | `0x2f302f5e16d464bd252d5951bafcbed0cbc398cfe6c4ad46d04469a1eead4323` = keccak256("income-over-v1") |
| vkHash | `0x543b70decfe8abad980bb3167a556aedb741c9d36946993c55dca2014a22a5ac` |
| ceremonyContributions | 1 (one Super Wallet contribution plus a public Xphere beacon; see TRANSCRIPT.md) |
| Committed attribute | `observedMonthlyIncome` in minor units = amount x 100. The commitment covers the amount only, so the currency is bound by the circuit id: the issuer commits under income-over-<currency>-v1, never under this name |
| Public signals | `commitment`, `threshold`, `nonce` (snarkjs order; the commitment first, the nonce last) |
| Verifier call | `verifyProof(uint256[2],uint256[2][2],uint256[2],uint256[3])` |
| Request (`<sw-verify request>`) | none: a request names a currency circuit, e.g. income>=2000000:KRW -> income-over-krw-v1 |
| Registry | `0x852688D815410e3FEa015FD3a07028BF6b981d80` on Xphere (chain id 20250217). **Not registered, and never will be; nothing is committed under this id.** This key serves the per-currency income circuits ([income-over-krw-v1](../income-over-krw-v1/), [income-over-lak-v1](../income-over-lak-v1/), [income-over-vnd-v1](../income-over-vnd-v1/), [income-over-thb-v1](../income-over-thb-v1/), [income-over-kgs-v1](../income-over-kgs-v1/), [income-over-usd-v1](../income-over-usd-v1/)), each registered with this circuit's verifier contract and vkHash under its own id. The commitment covers the amount only, so the currency is bound by which id the issuer commits under (spec section 7.2) |
| uri | https://trendy.storydot.kr/sdk/zk/income-over-v1/ |

## What a verifier checks

Nothing is ever accepted under this name: the registry has no entry for its id and no commitment is
made under it, so a verifier refuses a proof that names it. For an income in a currency, see the
currency circuit's README (for example [income-over-krw-v1](../income-over-krw-v1/)): it lists the
four checks, the fourth being `threshold` >= minIncome x 100 (minor units) and < 2^48.

## Files

| File | What it is |
|---|---|
| `income-over-v1.circom`, `templates/`, `lib/` | The circuit (circom 2.1.9; circomlib 2.0.5 for Poseidon, bitify and comparators) |
| `income-over-v1.r1cs` | The constraint system (385 constraints); needed to check the ceremony |
| `income-over-v1.wasm` | Witness calculator, for proving |
| `income-over-v1.zkey` | The final proving key; contains the whole contribution chain |
| `verification_key.json` | The Groth16 verification key |
| `Verifier.sol`, `solc-input.json` | The snarkjs Solidity verifier and the exact compiler input (solc 0.8.24, optimizer 200 runs, evmVersion paris) |
| `circuit.json` | Machine-readable manifest and ceremony record |
| `TRANSCRIPT.md` | The ceremony, step by step, with every hash |

## Reproduce

```sh
npm install circomlib@2.0.5 circom2@0.2.23
npx circom2 income-over-v1.circom --r1cs --wasm --O2 -l . -l node_modules
sha256sum income-over-v1.r1cs      # 973822e429ec1fa381f03b41c490a4e027202ceca8add9fb51e2e4d035a0c2b7

npx --yes solc@0.8.24 --standard-json < solc-input.json > solc-output.json
# keccak256(runtime bytecode of contracts/income-over-v1.Verifier.sol:Groth16Verifier) = 0xf860b9e8a04ef653d48ba078db430621643b027839361eef754fb6c1aca59103
# (../tier-threshold-v1/check-bytecode.cjs compares it with the deployed contract)
```

vkHash: RFC 8785 canonical JSON of `verification_key.json` (keys sorted, no whitespace), then
keccak256: `node scripts/governance.cjs vk-hash verification_key.json` in chain/trust-registry, or
`vkHash()` in @superwallet/zk-kit.
