@clearproof/content 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/content/explainers/pilot-proof-public-signals.md +80 -0
- package/content/explainers/portable-evidence-review.md +103 -0
- package/content/explainers/usd-cents-without-a-price-feed.md +106 -0
- package/content/explainers/verify-independently.md +106 -0
- package/content/explainers/what-clearproof-does.md +92 -0
- package/content/explainers/who-verifies-what.md +86 -0
- package/content/recipes/deploy-contracts.md +45 -0
- package/content/recipes/full-walkthrough.md +84 -0
- package/content/recipes/generate-proof.md +43 -0
- package/content/recipes/update-sanctions.md +35 -0
- package/content/recipes/verify-onchain.md +41 -0
- package/content/recipes/verify-proof.md +36 -0
- package/content/signals.yaml +128 -0
- package/content/topics/api.md +61 -0
- package/content/topics/architecture.md +50 -0
- package/content/topics/circuits.md +66 -0
- package/content/topics/contracts.md +60 -0
- package/content/topics/gdpr.md +36 -0
- package/content/topics/quickstart.md +77 -0
- package/content/topics/sdk.md +56 -0
- package/content/topics/security.md +33 -0
- package/content/topics/troubleshooting.md +109 -0
- package/content/updates/2026-09-09-adoption-roadmap.md +27 -0
- package/content/updates/2026-09-12-full-walkthrough.md +31 -0
- package/content/updates/2026-09-12-npm-status.md +27 -0
- package/content/updates/2026-09-12-proof-boundaries.md +40 -0
- package/content/updates/2026-09-21-sanctions-schedule.md +43 -0
- package/content/updates/2026-09-25-pilot-transfer-v3.md +60 -0
- package/dist/explainers.d.ts +29 -0
- package/dist/explainers.d.ts.map +1 -0
- package/dist/explainers.js +71 -0
- package/dist/explainers.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -0
- package/dist/parser.d.ts +25 -0
- package/dist/parser.d.ts.map +1 -0
- package/dist/parser.js +97 -0
- package/dist/parser.js.map +1 -0
- package/dist/recipes.d.ts +28 -0
- package/dist/recipes.d.ts.map +1 -0
- package/dist/recipes.js +103 -0
- package/dist/recipes.js.map +1 -0
- package/dist/signals.d.ts +18 -0
- package/dist/signals.d.ts.map +1 -0
- package/dist/signals.js +34 -0
- package/dist/signals.js.map +1 -0
- package/dist/topics.d.ts +18 -0
- package/dist/topics.d.ts.map +1 -0
- package/dist/topics.js +41 -0
- package/dist/topics.js.map +1 -0
- package/dist/updates.d.ts +27 -0
- package/dist/updates.d.ts.map +1 -0
- package/dist/updates.js +69 -0
- package/dist/updates.js.map +1 -0
- package/package.json +42 -0
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Full End-to-End Walkthrough
|
|
3
|
+
prereqs:
|
|
4
|
+
- api-running
|
|
5
|
+
- circuits-compiled
|
|
6
|
+
- contracts-deployed
|
|
7
|
+
- sepolia-rpc
|
|
8
|
+
estimated-time: 10 min
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Full End-to-End Walkthrough
|
|
12
|
+
|
|
13
|
+
> **Legacy demo path.** This recipe uses the 16-signal legacy profile (`/proof/generate`, `/proof/verify`). It does not exercise the current `pilot-transfer-v3` workflow; for that, follow the [local acceptance guide](https://github.com/repfigit/clearproof/blob/main/docs/operations/local-pilot-acceptance.md).
|
|
14
|
+
|
|
15
|
+
Complete compliance flow: issue a credential, generate a proof, verify off-chain, and record on-chain.
|
|
16
|
+
|
|
17
|
+
The local API defaults to API-key auth:
|
|
18
|
+
|
|
19
|
+
```bash:run
|
|
20
|
+
export CLEARPROOF_API_KEY="dev-api-key"
|
|
21
|
+
export AUTH_MODE="api-key"
|
|
22
|
+
export API_KEY="$CLEARPROOF_API_KEY"
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## 1. Build the sanctions tree
|
|
26
|
+
|
|
27
|
+
```bash:run
|
|
28
|
+
python scripts/build_sanctions_tree.py --offline
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Expected: Sanctions tree built with root hash and leaf count displayed
|
|
32
|
+
|
|
33
|
+
## 2. Issue a zkKYC credential
|
|
34
|
+
|
|
35
|
+
```bash:run
|
|
36
|
+
curl -s -X POST http://localhost:8000/credential/issue \
|
|
37
|
+
-H "X-API-Key: $CLEARPROOF_API_KEY" \
|
|
38
|
+
-H "Content-Type: application/json" \
|
|
39
|
+
-d '{"issuer_did":"did:web:vasp.example.com","subject_wallet":"0x1234abcd5678ef901234abcd5678ef9012345678","jurisdiction":"US","kyc_tier":"retail"}'
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Expected: 200 with `credential_id` and `commitment`
|
|
43
|
+
|
|
44
|
+
## 3. Generate a compliance proof
|
|
45
|
+
|
|
46
|
+
```bash:run
|
|
47
|
+
curl -s -X POST http://localhost:8000/proof/generate \
|
|
48
|
+
-H "X-API-Key: $CLEARPROOF_API_KEY" \
|
|
49
|
+
-H "Content-Type: application/json" \
|
|
50
|
+
-d '{"credential_id":"CRED_ID_FROM_STEP_2","wallet_address":"0x1234abcd5678ef901234abcd5678ef9012345678","amount_usd":500,"asset":"USDC","destination_wallet":"0xabcd1234abcd1234abcd1234abcd1234abcd1234","jurisdiction":"US","idempotency_key":"recipe-full-001"}'
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Expected: 200 with `compliance_proof` (Groth16 proof + 16 public signals) and `encrypted_pii`
|
|
54
|
+
|
|
55
|
+
## 4. Verify the proof off-chain
|
|
56
|
+
|
|
57
|
+
```bash:run
|
|
58
|
+
curl -s -X POST http://localhost:8000/proof/verify \
|
|
59
|
+
-H "X-API-Key: $CLEARPROOF_API_KEY" \
|
|
60
|
+
-H "Content-Type: application/json" \
|
|
61
|
+
-d '{"proof_id":"PROOF_ID_FROM_STEP_3","groth16_proof":{"pi_a":["..."],"pi_b":["..."],"pi_c":["..."]},"public_signals":["1","0","..."],"expected_amount_tier":1,"originator_vasp_did":"did:web:vasp.example.com","transfer_timestamp":1711929600}'
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Expected: 200 with `valid: true` and `is_compliant: true`
|
|
65
|
+
|
|
66
|
+
## 5. Record the proof on-chain
|
|
67
|
+
|
|
68
|
+
```bash:run
|
|
69
|
+
export PROOF_PATH="$PWD/artifacts/latest_proof.json"
|
|
70
|
+
export TRANSFER_ID="recipe-transfer-001"
|
|
71
|
+
export VASP_DID="did:web:vasp.example.com"
|
|
72
|
+
cd packages/contracts && npx hardhat run scripts/verify-onchain.ts --network sepolia
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Expected: Transaction hash and `ProofVerified` event emitted on ComplianceRegistry
|
|
76
|
+
|
|
77
|
+
## 6. Confirm on-chain recording
|
|
78
|
+
|
|
79
|
+
```bash:run
|
|
80
|
+
export TRANSFER_ID="recipe-transfer-001"
|
|
81
|
+
cd packages/contracts && npx hardhat run scripts/check-transfer.ts --network sepolia
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Expected: `isVerified` returns `true` for the transfer ID
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Generate a Compliance Proof
|
|
3
|
+
prereqs:
|
|
4
|
+
- api-running
|
|
5
|
+
- circuits-compiled
|
|
6
|
+
estimated-time: 2 min
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Generate a Compliance Proof
|
|
10
|
+
|
|
11
|
+
> **Legacy demo path.** This recipe uses the 16-signal legacy profile (`/proof/generate`, `/proof/verify`). It does not exercise the current `pilot-transfer-v3` workflow; for that, follow the [local acceptance guide](https://github.com/repfigit/clearproof/blob/main/docs/operations/local-pilot-acceptance.md).
|
|
12
|
+
|
|
13
|
+
Issue a zkKYC credential and then generate a Groth16 compliance proof against it.
|
|
14
|
+
|
|
15
|
+
The local API defaults to API-key auth:
|
|
16
|
+
|
|
17
|
+
```bash:run
|
|
18
|
+
export CLEARPROOF_API_KEY="dev-api-key"
|
|
19
|
+
export AUTH_MODE="api-key"
|
|
20
|
+
export API_KEY="$CLEARPROOF_API_KEY"
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## 1. Issue a credential
|
|
24
|
+
|
|
25
|
+
```bash:run
|
|
26
|
+
curl -s -X POST http://localhost:8000/credential/issue \
|
|
27
|
+
-H "X-API-Key: $CLEARPROOF_API_KEY" \
|
|
28
|
+
-H "Content-Type: application/json" \
|
|
29
|
+
-d '{"issuer_did":"did:web:vasp.example.com","subject_wallet":"0x1234abcd5678ef901234abcd5678ef9012345678","jurisdiction":"US","kyc_tier":"retail"}'
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Expected: 200 with `credential_id` and `commitment`
|
|
33
|
+
|
|
34
|
+
## 2. Generate proof
|
|
35
|
+
|
|
36
|
+
```bash:run
|
|
37
|
+
curl -s -X POST http://localhost:8000/proof/generate \
|
|
38
|
+
-H "X-API-Key: $CLEARPROOF_API_KEY" \
|
|
39
|
+
-H "Content-Type: application/json" \
|
|
40
|
+
-d '{"credential_id":"CRED_ID_FROM_STEP_1","wallet_address":"0x1234abcd5678ef901234abcd5678ef9012345678","amount_usd":500,"asset":"USDC","destination_wallet":"0xabcd1234abcd1234abcd1234abcd1234abcd1234","jurisdiction":"US","idempotency_key":"recipe-generate-001"}'
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Expected: 200 with `compliance_proof` containing Groth16 proof, 16 public signals, and `encrypted_pii`
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Update Sanctions Tree
|
|
3
|
+
prereqs:
|
|
4
|
+
- api-running
|
|
5
|
+
- contracts-deployed
|
|
6
|
+
estimated-time: 2 min
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Update Sanctions Tree
|
|
10
|
+
|
|
11
|
+
Rebuild the sanctions Merkle tree from OFAC/UN/EU lists and relay the new root to the on-chain SanctionsOracle.
|
|
12
|
+
|
|
13
|
+
## 1. Build the sanctions tree
|
|
14
|
+
|
|
15
|
+
```bash:run
|
|
16
|
+
python scripts/build_sanctions_tree.py --offline
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Expected: Tree built with leaf count printed, root hash displayed. The `--offline` flag uses cached list data; omit it to fetch fresh lists from OFAC/UN/EU sources.
|
|
20
|
+
|
|
21
|
+
## 2. Relay the new root to SanctionsOracle
|
|
22
|
+
|
|
23
|
+
```bash:run
|
|
24
|
+
python scripts/relay_sanctions_root.py --network sepolia
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Expected: Transaction hash printed, `RootUpdated` event emitted on SanctionsOracle with new root and leaf count
|
|
28
|
+
|
|
29
|
+
## 3. Verify the oracle is not stale
|
|
30
|
+
|
|
31
|
+
```bash:run
|
|
32
|
+
cd packages/contracts && npx hardhat run scripts/check-oracle-staleness.ts --network sepolia
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Expected: `isStale` returns `false`, `lastUpdated` is recent
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Verify a Proof On-Chain
|
|
3
|
+
prereqs:
|
|
4
|
+
- contracts-deployed
|
|
5
|
+
- proof-generated
|
|
6
|
+
- sepolia-rpc
|
|
7
|
+
estimated-time: 3 min
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Verify a Proof On-Chain
|
|
11
|
+
|
|
12
|
+
Submit a compliance proof to the ComplianceRegistry contract on Sepolia testnet. The contract performs 14 checks including Groth16 verification, sanctions root validation, and nullifier uniqueness.
|
|
13
|
+
|
|
14
|
+
## 1. Set environment variables
|
|
15
|
+
|
|
16
|
+
```bash:run
|
|
17
|
+
export SEPOLIA_RPC_URL="https://rpc.sepolia.org"
|
|
18
|
+
export DEPLOYER_PRIVATE_KEY="YOUR_VASP_WALLET_PRIVATE_KEY"
|
|
19
|
+
export COMPLIANCE_REGISTRY="YOUR_COMPLIANCE_REGISTRY_ADDRESS" # optional if deployments/sepolia.json exists
|
|
20
|
+
export PROOF_PATH="$PWD/../../artifacts/latest_proof.json"
|
|
21
|
+
export TRANSFER_ID="recipe-transfer-001"
|
|
22
|
+
export VASP_DID="did:web:vasp.example.com"
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Expected: No output (variables set)
|
|
26
|
+
|
|
27
|
+
## 2. Submit proof to ComplianceRegistry
|
|
28
|
+
|
|
29
|
+
```bash:run
|
|
30
|
+
cd packages/contracts && npx hardhat run scripts/verify-onchain.ts --network sepolia
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Expected: Transaction hash and `ProofVerified` event emitted with the blinded nullifier
|
|
34
|
+
|
|
35
|
+
## 3. Confirm the transfer is recorded
|
|
36
|
+
|
|
37
|
+
```bash:run
|
|
38
|
+
cd packages/contracts && npx hardhat run scripts/check-transfer.ts --network sepolia
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Expected: `isVerified` returns `true` for the transfer ID
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Verify a Proof Off-Chain
|
|
3
|
+
prereqs:
|
|
4
|
+
- api-running
|
|
5
|
+
- proof-generated
|
|
6
|
+
estimated-time: 1 min
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Verify a Proof Off-Chain
|
|
10
|
+
|
|
11
|
+
> **Legacy demo path.** This recipe uses the 16-signal legacy profile (`/proof/generate`, `/proof/verify`). It does not exercise the current `pilot-transfer-v3` workflow; for that, follow the [local acceptance guide](https://github.com/repfigit/clearproof/blob/main/docs/operations/local-pilot-acceptance.md).
|
|
12
|
+
|
|
13
|
+
Take an existing compliance proof and verify it locally using the API server. This does not interact with any blockchain.
|
|
14
|
+
|
|
15
|
+
The local API defaults to API-key auth:
|
|
16
|
+
|
|
17
|
+
```bash:run
|
|
18
|
+
export CLEARPROOF_API_KEY="dev-api-key"
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## 1. Verify the proof
|
|
22
|
+
|
|
23
|
+
```bash:run
|
|
24
|
+
curl -s -X POST http://localhost:8000/proof/verify \
|
|
25
|
+
-H "X-API-Key: $CLEARPROOF_API_KEY" \
|
|
26
|
+
-H "Content-Type: application/json" \
|
|
27
|
+
-d '{"proof_id":"PROOF_ID_FROM_GENERATE","groth16_proof":{"pi_a":["..."],"pi_b":["..."],"pi_c":["..."]},"public_signals":["1","0","..."],"expected_amount_tier":2,"originator_vasp_did":"did:web:vasp.example.com","transfer_timestamp":1711929600}'
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Expected: 200 with `valid: true` and `compliance_attestations` showing `is_compliant: true`
|
|
31
|
+
|
|
32
|
+
The verification checks:
|
|
33
|
+
- Groth16 proof is cryptographically valid against the verification key
|
|
34
|
+
- `is_compliant` signal equals 1
|
|
35
|
+
- Amount tier matches the expected tier
|
|
36
|
+
- Transfer timestamp is reasonable
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
signals:
|
|
2
|
+
- index: 0
|
|
3
|
+
name: is_compliant
|
|
4
|
+
type: bit
|
|
5
|
+
description: 1 for the encoded circuit checks; not a legal compliance determination
|
|
6
|
+
source: circuits/compliance.circom
|
|
7
|
+
onChainUsage: Must equal 1 for proof acceptance
|
|
8
|
+
isOutput: true
|
|
9
|
+
|
|
10
|
+
- index: 1
|
|
11
|
+
name: sar_review_flag
|
|
12
|
+
type: bit
|
|
13
|
+
description: Public tier-derived advisory bit; 1 if amount_tier >= 3, not a suspicious-activity determination
|
|
14
|
+
source: circuits/amount_tier.circom
|
|
15
|
+
onChainUsage: Emitted as the review bit in the development ProofVerified event
|
|
16
|
+
isOutput: true
|
|
17
|
+
|
|
18
|
+
- index: 2
|
|
19
|
+
name: sanctions_tree_root
|
|
20
|
+
type: field
|
|
21
|
+
description: Merkle root of the supplied sanctions dataset; source completeness and freshness require verification
|
|
22
|
+
source: circuits/compliance.circom
|
|
23
|
+
onChainUsage: Checked against SanctionsOracle.currentRoot()
|
|
24
|
+
isOutput: false
|
|
25
|
+
|
|
26
|
+
- index: 3
|
|
27
|
+
name: issuer_tree_root
|
|
28
|
+
type: field
|
|
29
|
+
description: Merkle root of the trusted VASP issuer tree
|
|
30
|
+
source: circuits/compliance.circom
|
|
31
|
+
onChainUsage: Checked against VASPRegistry.issuerMerkleRoot()
|
|
32
|
+
isOutput: false
|
|
33
|
+
|
|
34
|
+
- index: 4
|
|
35
|
+
name: amount_tier
|
|
36
|
+
type: uint64
|
|
37
|
+
description: Amount bucket 1 through 4 under the supplied ordered thresholds
|
|
38
|
+
source: circuits/amount_tier.circom
|
|
39
|
+
onChainUsage: Used for tier-based compliance rules
|
|
40
|
+
isOutput: false
|
|
41
|
+
|
|
42
|
+
- index: 5
|
|
43
|
+
name: transfer_timestamp
|
|
44
|
+
type: uint64
|
|
45
|
+
description: Unix timestamp of the transfer
|
|
46
|
+
source: circuits/compliance.circom
|
|
47
|
+
onChainUsage: Must be <= block.timestamp
|
|
48
|
+
isOutput: false
|
|
49
|
+
|
|
50
|
+
- index: 6
|
|
51
|
+
name: jurisdiction_code
|
|
52
|
+
type: uint16
|
|
53
|
+
description: 16-bit jurisdiction input; integrations must agree on its encoding
|
|
54
|
+
source: circuits/credential_validity.circom
|
|
55
|
+
onChainUsage: Used for jurisdiction-specific compliance rules
|
|
56
|
+
isOutput: false
|
|
57
|
+
|
|
58
|
+
- index: 7
|
|
59
|
+
name: credential_commitment
|
|
60
|
+
type: field
|
|
61
|
+
description: Poseidon hash of credential preimage (issuer_did, kyc_tier, sanctions_clear, issued_at, expires_at)
|
|
62
|
+
source: circuits/credential_validity.circom
|
|
63
|
+
onChainUsage: Used for credential binding
|
|
64
|
+
isOutput: false
|
|
65
|
+
|
|
66
|
+
- index: 8
|
|
67
|
+
name: tier2_threshold
|
|
68
|
+
type: uint64
|
|
69
|
+
description: Inclusive lower boundary in USD cents for tier 2
|
|
70
|
+
source: circuits/amount_tier.circom
|
|
71
|
+
onChainUsage: Jurisdiction-configurable threshold
|
|
72
|
+
isOutput: false
|
|
73
|
+
|
|
74
|
+
- index: 9
|
|
75
|
+
name: tier3_threshold
|
|
76
|
+
type: uint64
|
|
77
|
+
description: Inclusive lower boundary in USD cents for tier 3
|
|
78
|
+
source: circuits/amount_tier.circom
|
|
79
|
+
onChainUsage: Jurisdiction-configurable threshold
|
|
80
|
+
isOutput: false
|
|
81
|
+
|
|
82
|
+
- index: 10
|
|
83
|
+
name: tier4_threshold
|
|
84
|
+
type: uint64
|
|
85
|
+
description: Inclusive lower boundary in USD cents for tier 4
|
|
86
|
+
source: circuits/amount_tier.circom
|
|
87
|
+
onChainUsage: Jurisdiction-configurable threshold
|
|
88
|
+
isOutput: false
|
|
89
|
+
|
|
90
|
+
- index: 11
|
|
91
|
+
name: domain_chain_id
|
|
92
|
+
type: uint256
|
|
93
|
+
description: Ethereum chain ID (e.g., 1=mainnet, 11155111=Sepolia)
|
|
94
|
+
source: circuits/compliance.circom
|
|
95
|
+
onChainUsage: Must equal block.chainid
|
|
96
|
+
isOutput: false
|
|
97
|
+
|
|
98
|
+
- index: 12
|
|
99
|
+
name: domain_contract_hash
|
|
100
|
+
type: field
|
|
101
|
+
description: keccak256 of the encoded ComplianceRegistry address reduced modulo the scalar field
|
|
102
|
+
source: circuits/compliance.circom
|
|
103
|
+
onChainUsage: Must equal keccak256(address(this)) % BN128_R
|
|
104
|
+
isOutput: false
|
|
105
|
+
|
|
106
|
+
- index: 13
|
|
107
|
+
name: transfer_id_hash
|
|
108
|
+
type: field
|
|
109
|
+
description: Registry expects keccak256 of encoded transferId reduced modulo the scalar field; API consistency remains open
|
|
110
|
+
source: circuits/compliance.circom
|
|
111
|
+
onChainUsage: Checked against transferId by the registry, alongside duplicate-record and nullifier checks
|
|
112
|
+
isOutput: false
|
|
113
|
+
|
|
114
|
+
- index: 14
|
|
115
|
+
name: credential_nullifier
|
|
116
|
+
type: field
|
|
117
|
+
description: Poseidon(credential_commitment, transfer_id_hash) -- one-time-use value stored on-chain
|
|
118
|
+
source: circuits/compliance.circom
|
|
119
|
+
onChainUsage: Stored in usedNullifiers mapping, checked for uniqueness
|
|
120
|
+
isOutput: false
|
|
121
|
+
|
|
122
|
+
- index: 15
|
|
123
|
+
name: proof_expires_at
|
|
124
|
+
type: uint64
|
|
125
|
+
description: Unix timestamp after which proof is invalid
|
|
126
|
+
source: circuits/compliance.circom
|
|
127
|
+
onChainUsage: Must be >= block.timestamp
|
|
128
|
+
isOutput: false
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: API Reference
|
|
3
|
+
category: reference
|
|
4
|
+
order: 5
|
|
5
|
+
cli-topic: api
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# API reference
|
|
9
|
+
|
|
10
|
+
The Python API (FastAPI) is a development component in the source checkout, reviewed September 25, 2026. It is not part of the published npm packages. Use the running application's [local OpenAPI UI](http://localhost:8000/docs) for exact request and response schemas.
|
|
11
|
+
|
|
12
|
+
Protected routes require the configured authentication. Pilot routes also require an authenticated tenant principal with explicit roles and issuer scope; there is no implicit administrator override. PostgreSQL, storage keys and tenant trust configuration are required for the pilot routes. See [deployment](/docs/deployment).
|
|
13
|
+
|
|
14
|
+
## Pilot routes
|
|
15
|
+
|
|
16
|
+
| Route | Purpose |
|
|
17
|
+
| --- | --- |
|
|
18
|
+
| `POST /pilot/credential/enroll` | Enroll a credential with the holder wallet's signed consent |
|
|
19
|
+
| `POST /pilot/credential/revoke` | Revoke an enrolled credential permanently |
|
|
20
|
+
| `POST /pilot/policy/approve` | Approve a reviewed policy version (activation is a separate step) |
|
|
21
|
+
| `POST /pilot/policy/diff` | Compare a proposed policy against supplied cases |
|
|
22
|
+
| `POST /pilot/policy/diff/stored` | Compare a proposed policy against retained evidence |
|
|
23
|
+
| `POST /pilot/proof/inspect` | Read-only inspection of a current proof against current state; never consumes |
|
|
24
|
+
| `POST /pilot/proof/evaluate` | Explained policy evaluation of a current proof |
|
|
25
|
+
| `POST /pilot/proof/authorize` | Consume one authorization after an `ALLOW`, sealing information to the recipient |
|
|
26
|
+
| `POST /pilot/proof/observe` | Record a non-authorizing observation |
|
|
27
|
+
| `POST /pilot/proof/observations/read`, `/list`, `/report` | Read observations and cohort reports |
|
|
28
|
+
| `POST /pilot/events/ingest` | Ingest signed custody, counterparty or chain events |
|
|
29
|
+
| `POST /pilot/events/investigate` | Transfer investigation timeline |
|
|
30
|
+
| `POST /pilot/events/queue` | Paginated investigation queue |
|
|
31
|
+
| `POST /pilot/fireblocks/{integration_id}` | Verify and retain a signed Fireblocks notification from a tenant relay |
|
|
32
|
+
| `GET /pilot/usage` | Retained record counters (not billable charges) |
|
|
33
|
+
|
|
34
|
+
## Wallet ownership extension
|
|
35
|
+
|
|
36
|
+
| Route | Purpose |
|
|
37
|
+
| --- | --- |
|
|
38
|
+
| `POST /wallet/ownership/challenge` | Five-minute EOA signing challenge for an enrolled credential |
|
|
39
|
+
| `POST /wallet/ownership/verify` | Verify the EIP-191 signature; issue a 24-hour attestation |
|
|
40
|
+
| `GET /wallet/ownership/attestations/{attestation_id}` | Current attestation eligibility |
|
|
41
|
+
| `POST /wallet/ownership/revoke` | Revoke an attestation |
|
|
42
|
+
| `POST /wallet/ownership/credential` | Issue the optional versioned extension credential |
|
|
43
|
+
|
|
44
|
+
The extension circuit is staged; no deployed verifier accepts it. See the [wallet ownership guide](https://github.com/repfigit/clearproof/blob/main/docs/internal/WALLET_OWNERSHIP.md).
|
|
45
|
+
|
|
46
|
+
## Shared and legacy routes
|
|
47
|
+
|
|
48
|
+
| Route | Purpose |
|
|
49
|
+
| --- | --- |
|
|
50
|
+
| `GET /health` | Process liveness, not pilot readiness |
|
|
51
|
+
| `GET /metrics` | Operational counters |
|
|
52
|
+
| `GET /.well-known/clearproof.json` | Discovery metadata: exact `did:web` identity and HPKE key |
|
|
53
|
+
| `GET /auth/nonce`, `POST /auth/verify` | SIWE challenge and verification |
|
|
54
|
+
| `POST /credential/issue`, `POST /credential/revoke` | Legacy development credentials |
|
|
55
|
+
| `POST /proof/generate`, `POST /proof/verify` | Legacy 16-signal demo proof generation and verification |
|
|
56
|
+
|
|
57
|
+
The legacy routes serve the demo profile. A legacy proof is never current pilot authorization.
|
|
58
|
+
|
|
59
|
+
## Limits
|
|
60
|
+
|
|
61
|
+
A successful response is not legal compliance, settlement or a live counterparty's acceptance. Inspection and observation results never authorize a transfer. Only `/pilot/proof/authorize` consumes an authorization, and only after an `ALLOW`. See [architecture](/docs/architecture) and [security](/docs/security).
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Architecture
|
|
3
|
+
category: concepts
|
|
4
|
+
order: 2
|
|
5
|
+
cli-topic: architecture
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Architecture
|
|
9
|
+
|
|
10
|
+
clearproof combines a Python API with PostgreSQL storage, Circom circuits, TypeScript proof tooling and Solidity contracts. The pilot workflow below is implemented in the source checkout and tested locally with synthetic data and real development proofs. It has not been independently audited or deployed to production.
|
|
11
|
+
|
|
12
|
+
## Pilot workflow
|
|
13
|
+
|
|
14
|
+
```mermaid
|
|
15
|
+
flowchart LR
|
|
16
|
+
Enroll[Wallet-signed credential enrollment] --> Roots[Signed issuance, issuer and sanctions roots]
|
|
17
|
+
Roots --> Prove[pilot-transfer-v3 Groth16 proof]
|
|
18
|
+
Policy[Reviewed, active policy] --> Authorize
|
|
19
|
+
Prove --> Authorize[Authorization service: current state + policy ALLOW]
|
|
20
|
+
Authorize --> Seal[Information sealed to recipient's HPKE key]
|
|
21
|
+
Authorize --> Receipt[Consumed receipt in PostgreSQL]
|
|
22
|
+
Receipt --> Mirror[Optional on-chain receipt mirror]
|
|
23
|
+
Seal --> Peer[Counterparty verifies and responds]
|
|
24
|
+
Receipt --> Evidence[Encrypted evidence export for offline review]
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Responsibilities
|
|
28
|
+
|
|
29
|
+
The **circuit** proves the transfer projection, credential, issuer membership and sanctions non-membership relationships. See [circuits](/docs/circuits).
|
|
30
|
+
|
|
31
|
+
The **authorization service** checks everything the circuit cannot: the current roots and their signatures, credential revocation, the active policy, signed valuation and external facts, and the real proof pairing. Only a policy `ALLOW` can consume an authorization. `DENY`, `REVIEW`, `INDETERMINATE`, invalid pairing and untrusted inputs cannot. On `ALLOW` it seals the approved transfer information to a trusted recipient key and records the evidence, the receipt and the consumed nullifier in one PostgreSQL transaction.
|
|
32
|
+
|
|
33
|
+
The **contract** (`PilotCurrentRegistry`) mirrors receipts that were already consumed, under checkpoints published by a trusted publisher. It checks the chain ID, its own address and the expiry, but it cannot create an authorization or detect a publisher that lies about private records.
|
|
34
|
+
|
|
35
|
+
Read-only inspection and observation never consume an authorization.
|
|
36
|
+
|
|
37
|
+
## Around the proof
|
|
38
|
+
|
|
39
|
+
- **Policy review:** explained outcomes, stored comparisons of a proposed policy against past cases, and separate approval and activation history.
|
|
40
|
+
- **Investigations:** read-only timelines that join policy, counterparty, custody, chain and evidence events, keeping duplicates, ordering and unresolved conflicts visible.
|
|
41
|
+
- **Historical evidence:** recipient-encrypted exports that an independent reviewer can check offline after the proof expires, using separately configured trust.
|
|
42
|
+
- **Observation mode:** runs alongside an existing workflow and records explained outcomes without authorizing anything.
|
|
43
|
+
|
|
44
|
+
## Legacy path
|
|
45
|
+
|
|
46
|
+
The original `compliance.circom` profile, `/proof/generate`, `/proof/verify`, the `ComplianceRegistry` contract and the hybrid payload remain as a separate demo and parity path. Their proofs are not current pilot authorization.
|
|
47
|
+
|
|
48
|
+
## Not yet done
|
|
49
|
+
|
|
50
|
+
Live provider and counterparty interoperability, remote TRP/TRISA conformance, re-screening from an upstream feed, managed distribution, an independent audit and a production setup are separate follow-on gates. See [project status](/docs/status).
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Circuits
|
|
3
|
+
category: concepts
|
|
4
|
+
order: 3
|
|
5
|
+
cli-topic: circuits
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Circuits
|
|
9
|
+
|
|
10
|
+
clearproof uses Circom and Groth16 over BN254. CI compiles with circom **2.2.2**. These are unaudited development components with development-only proving keys. See [security](/docs/security).
|
|
11
|
+
|
|
12
|
+
There are two proof profiles. **Never select a profile by its signal count.**
|
|
13
|
+
|
|
14
|
+
| Profile | Circuit | Public signals | Status |
|
|
15
|
+
| --- | --- | --- | --- |
|
|
16
|
+
| `pilot-transfer-v3` | `pilot_compliance.circom` | 8 | **Current** pilot profile |
|
|
17
|
+
| `pilot-transfer-v2` / `v1` | same circuit, earlier tree depths or binding | 8 | Historical; current checks reject them |
|
|
18
|
+
| Legacy | `compliance.circom` | 16 | Separate demo and parity path; never current pilot authorization |
|
|
19
|
+
|
|
20
|
+
## Current profile: pilot-transfer-v3
|
|
21
|
+
|
|
22
|
+
The circuit is instantiated as `PilotCompliance(32, 20, 20)`: an issuance tree of depth 32 (about 4.3 billion credentials per issuer), an authorized-issuer tree of depth 20 and a sanctions tree of depth 20 (1,048,574 addresses plus two boundary leaves). It has 95,408 constraints and needs `2^17` powers-of-tau parameters. The authoritative statement is [`specs/pilot-transfer-v3.md`](https://github.com/repfigit/clearproof/blob/main/specs/pilot-transfer-v3.md).
|
|
23
|
+
|
|
24
|
+
```text
|
|
25
|
+
PilotCompliance(32, 20, 20)
|
|
26
|
+
├── PilotTransferProjection 48 private transfer fields, exact valuation, private tier
|
|
27
|
+
├── PilotCredentialValidity credential, holder secret, issuance and issuer membership
|
|
28
|
+
└── PilotSanctionsGap × 2 raw-address non-membership for originator and beneficiary
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Public signals
|
|
32
|
+
|
|
33
|
+
| Index | Signal | What the circuit enforces |
|
|
34
|
+
| --- | --- | --- |
|
|
35
|
+
| 0 | `projection_commitment` | Commits to the private transfer projection, the exact credential and the issuance root |
|
|
36
|
+
| 1 | `authorized_issuer_root` | The credential's issuer is a member of this tree |
|
|
37
|
+
| 2 | `sanctions_root` | Neither wallet is in this sorted address tree |
|
|
38
|
+
| 3 | `authorization_nullifier` | Derived from the holder secret and the transfer's authorization scope |
|
|
39
|
+
| 4 | `evaluated_at` | Evaluation time; the credential must be valid at this time |
|
|
40
|
+
| 5 | `proof_expires_at` | Later than `evaluated_at`, and no later than the transfer expiry, the credential expiry or `evaluated_at` + 300 seconds |
|
|
41
|
+
| 6 | `domain_chain_id` | Equals the private deployment field only; the registry checks the real chain |
|
|
42
|
+
| 7 | `domain_registry` | Equals the private deployment field only; the registry checks its own address |
|
|
43
|
+
|
|
44
|
+
The amount, tier, wallets, jurisdiction, participants and credential fields are **private**. There is no public amount tier or review flag. A verifier must reconstruct signal 0 from its own authenticated records; a proof that verifies cryptographically says nothing about which transfer it covers until that check passes.
|
|
45
|
+
|
|
46
|
+
### What each part checks
|
|
47
|
+
|
|
48
|
+
- **Transfer projection.** All 48 fields are range-checked. Time ordering (observation ≤ creation ≤ evaluation < transfer expiry ≤ quote expiry), maximum age, decimals and nonzero identities are enforced. The amount is converted to USD cents with exact integer arithmetic, and the tier is derived privately from the policy thresholds.
|
|
49
|
+
- **Credential.** The credential commitment must be a member of the issuance root, and the issuer's leaf must be a member of the authorized-issuer root. The holder must know the secret behind the credential's holder commitment. Tenant, subject wallet and jurisdiction must match the transfer.
|
|
50
|
+
- **Sanctions.** A sorted-tree gap proof shows each raw 160-bit wallet address lies strictly between two adjacent leaves. Adjacency is derived from the Merkle path bits, and all compared values are range-checked.
|
|
51
|
+
- **Replay and expiry.** The nullifier stays the same for a given holder and transfer scope, so a replacement proof cannot be spent twice. The five-minute expiry bound is enforced in the circuit.
|
|
52
|
+
|
|
53
|
+
Some acceptance properties live outside the circuit. The authorization service checks current roots, revocation, policy and signed facts, and consumes the nullifier in PostgreSQL. `PilotCurrentRegistry` checks the chain ID, its own address and the expiry against published statements. See [architecture](/docs/architecture).
|
|
54
|
+
|
|
55
|
+
## Legacy profile
|
|
56
|
+
|
|
57
|
+
`ComplianceProof(20, 10)` in `compliance.circom` publishes 16 values, including `is_compliant`, a tier-derived `sar_review_flag`, the amount tier, the jurisdiction and the tier thresholds. It remains a demo and parity path with its own verifier, SDK function and tests. Legacy proofs are never current pilot authorization.
|
|
58
|
+
|
|
59
|
+
## Building development artifacts
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
.venv/bin/python scripts/test_development_circuits.py /absolute/new-directory \
|
|
63
|
+
--prepared-ptau /absolute/ppot_0080_17.ptau
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
This compiles both profiles, creates explicitly unapproved development keys and runs real proof round trips. CI uses the SHA-256-pinned [PSE perpetual powers of tau](https://pse-trusted-setup-ppot.s3.eu-central-1.amazonaws.com/pot28_0080/ppot_0080_17.ptau) file (`f807e065…3a367c`). Without `--prepared-ptau`, a local single-party `2^17` setup is generated, which can take over an hour. Development keys are not production keys; the production setup path is still an open decision (ADR 0004).
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Smart Contracts
|
|
3
|
+
category: concepts
|
|
4
|
+
order: 4
|
|
5
|
+
cli-topic: contracts
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Smart Contracts
|
|
9
|
+
|
|
10
|
+
The project includes two sets of EVM contracts. The **pilot contracts** verify and mirror current `pilot-transfer-v3` proofs; they exist in source and are tested locally, but are **not deployed** to any shared network. The **legacy contracts** serve the 16-signal demo profile; the Sepolia addresses below are historical testnet records of those. None of these contracts has been independently audited.
|
|
11
|
+
|
|
12
|
+
## Pilot contracts (source, not deployed)
|
|
13
|
+
|
|
14
|
+
**PilotGroth16Verifier** checks the eight-signal pilot proof against a verification key and artifact manifest digest fixed at construction. It reports `proofProfile` as `pilot-transfer-v3` and `assurance` as `development-unapproved`. Pairing alone does not reconstruct the transfer statement, check current state or consume a nullifier.
|
|
15
|
+
|
|
16
|
+
**PilotCurrentRegistry** publishes tenant checkpoints (revisioned heads for issuance, issuers, sanctions, credential, policy, valuation, participants and authorization) and statement bindings from one assigned publisher per tenant. `inspect` is a read-only call that checks a proof against a published statement, including the chain ID, the registry's own address and the expiry. It then mirrors receipts that PostgreSQL has already consumed. It cannot create an authorization, and it cannot detect a publisher that lies about private records. See the [registry trust boundary](https://github.com/repfigit/clearproof/blob/main/docs/internal/PILOT_CURRENT_REGISTRY.md).
|
|
17
|
+
|
|
18
|
+
## Legacy contracts: recorded Sepolia deployments
|
|
19
|
+
|
|
20
|
+
The July 20, 2026 manifest records these addresses for the legacy demo profile. Bytecode was present at all five on September 5, 2026. This check does not establish equivalence between every current source change and deployed bytecode.
|
|
21
|
+
|
|
22
|
+
| Contract | Sepolia address |
|
|
23
|
+
| --- | --- |
|
|
24
|
+
| Groth16Verifier | [0x6F8e6f64C5601Eb25716f45C78c9B7C9c0bde8EA](https://sepolia.etherscan.io/address/0x6F8e6f64C5601Eb25716f45C78c9B7C9c0bde8EA#code) |
|
|
25
|
+
| VASPRegistry | [0x99FE2813FD9D66Df43d1ce37d39341F5A7a557F0](https://sepolia.etherscan.io/address/0x99FE2813FD9D66Df43d1ce37d39341F5A7a557F0#code) |
|
|
26
|
+
| SanctionsOracle | [0x2822db7e67E1152a9cC81E44Df2182CA4662c7a2](https://sepolia.etherscan.io/address/0x2822db7e67E1152a9cC81E44Df2182CA4662c7a2#code) |
|
|
27
|
+
| ComplianceRegistry | [0x941F7f188843279C03D1960821B4332A40e806F7](https://sepolia.etherscan.io/address/0x941F7f188843279C03D1960821B4332A40e806F7#code) |
|
|
28
|
+
| SanctionsRootRelay | [0x911d8244F3b63a40040862dB0CC285A753036F87](https://sepolia.etherscan.io/address/0x911d8244F3b63a40040862dB0CC285A753036F87#code) |
|
|
29
|
+
|
|
30
|
+
## Groth16Verifier
|
|
31
|
+
|
|
32
|
+
Checks cryptographic proof validity against its verification key. That check alone does not establish source authenticity, current state, legal compliance or authorization to execute a transfer. Verifiers and artifacts must match the intended proof version.
|
|
33
|
+
|
|
34
|
+
## ComplianceRegistry
|
|
35
|
+
|
|
36
|
+
The development registry coordinates proof acceptance with other contracts. Its source checks duplicate transfer records, dependency pause/freshness, active VASP and submitting wallet, chain/contract domain, expiry and future timestamps, sanctions/issuer roots, transfer reference, configured thresholds, revocation and nullifier use. The current development code routes cryptographic verification through a versioned verifier router and configured selector.
|
|
37
|
+
|
|
38
|
+
Successful acceptance records the proof and consumes a nullifier. Read-only cryptographic verification in an SDK is a different operation. A recorded proof is not itself evidence of successful transfer settlement.
|
|
39
|
+
|
|
40
|
+
## VASPRegistry
|
|
41
|
+
|
|
42
|
+
Stores registered VASPs, authorized submitting wallets, jurisdictions, discovery endpoints and the issuer Merkle root. Registration and directory metadata must be interpreted under an explicit trust policy; they do not independently establish licensing or factual credential validity.
|
|
43
|
+
|
|
44
|
+
## SanctionsOracle
|
|
45
|
+
|
|
46
|
+
Stores a current root, update time, leaf count and bounded history. Controls include a one-hour update cooldown, a configured staleness window and a leaf-count floor. The history is a ring of up to 1,000 records, not a complete long-term evidence archive.
|
|
47
|
+
|
|
48
|
+
## SanctionsRootRelay
|
|
49
|
+
|
|
50
|
+
Forwards authorized root updates to the oracle. A local tree rebuild is not evidence that every intended chain received its update.
|
|
51
|
+
|
|
52
|
+
## Development
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
cd packages/contracts
|
|
56
|
+
npx hardhat compile
|
|
57
|
+
npx hardhat test
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Use the ABI and deployment configuration for your exact target. Existing testnet addresses must not be represented as an independently audited production release.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: GDPR Data-Minimization
|
|
3
|
+
category: concepts
|
|
4
|
+
order: 8
|
|
5
|
+
cli-topic: gdpr
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Privacy and data minimization
|
|
9
|
+
|
|
10
|
+
clearproof explores reducing disclosure by separating verification of specific predicates from encrypted exchange of required personal information. This is an architectural objective, not a GDPR exemption or a compliance certification.
|
|
11
|
+
|
|
12
|
+
## Encryption and proofs have different roles
|
|
13
|
+
|
|
14
|
+
A proof can establish its encoded statement without exposing every private witness value. Encrypted personal information can travel to an authorized recipient. The recipient may still need to obtain, verify and retain information under applicable requirements.
|
|
15
|
+
|
|
16
|
+
For covered EU crypto transfers, the Transfer of Funds Regulation sets information and missing-information obligations. An amount tier does not define a blanket exemption from those obligations. [EU Regulation 2023/1113, Articles 14–17](https://eur-lex.europa.eu/eli/reg/2023/1113/oj/eng)
|
|
17
|
+
|
|
18
|
+
Encrypted personal data remains personal data. Keeping it off-chain and limiting disclosure must be considered alongside purpose, access, retention and governance. [EDPB Guidelines 02/2025, final version 2, July 7, 2026](https://www.edpb.europa.eu/system/files/2026-07/edpb_guidelines_202502_blockchain_v2_en.pdf)
|
|
19
|
+
|
|
20
|
+
## What remains visible
|
|
21
|
+
|
|
22
|
+
A current `pilot-transfer-v3` proof publishes eight values: a commitment to the transfer and credential, the authorized-issuer and sanctions roots, a nullifier, the evaluation and expiry times, and the chain and registry it is bound to. The amount, tier, wallets, jurisdiction and participants stay private. See [circuits](/docs/circuits).
|
|
23
|
+
|
|
24
|
+
Commitments, nullifiers and timestamps are still not automatically anonymous. Linking them to other records, on-chain transactions or retained evidence can identify or correlate people. The legacy 16-signal demo circuit publishes more, including an amount tier, jurisdiction and a tier-derived review flag; do not use it where that metadata matters.
|
|
25
|
+
|
|
26
|
+
## Deployment questions
|
|
27
|
+
|
|
28
|
+
- Which facts actually need a private predicate proof?
|
|
29
|
+
- Which recipient is authorized to receive each piece of information?
|
|
30
|
+
- How are credentials, source data and recipient keys authenticated?
|
|
31
|
+
- What can repeated commitments, timestamps and status checks reveal?
|
|
32
|
+
- How are retention, access, deletion, incident handling and evidence export implemented?
|
|
33
|
+
|
|
34
|
+
Measure disclosure and operational data copying in the intended deployment. Neither encryption, ZK, nor explorer verification independently establishes compliance.
|
|
35
|
+
|
|
36
|
+
Read [current assurance limits](/docs/security).
|