One idea: prove the answer, keep the record.
Three parts: your vault, a proof and a consent contract.
The three parts
The vault
Encrypted on your device with a key from your wallet. Cura can host it, not read it.
The proof
Criteria are public inputs, your values private. Output: one bit and a nullifier.
The consent contract
Records who reads which fields until when, pays rewards and enforces revocation.
One study, one record, one bit
What the circuit sees. The middle column never leaves the device.
| Criterion (public input) | Your value (private input) | Circuit |
|---|---|---|
| Age between 40 and 7052 | 52 | satisfied |
| Diagnosis: type 2 diabetesYes, since 2019 | Yes, since 2019 | satisfied |
| HbA1c between 6.5 and 9.0 %7.1 % | 7.1 % | satisfied |
| Systolic blood pressure ≥ 130138 mmHg | 138 mmHg | satisfied |
Public outputs
eligible = 1
nullifier = hash(vault key, study id)
A failed criterion produces no proof, and nothing is sent.
The life of a consent
- Granted
Signed with the proof. The lab gets a key to the named fields.
- Active
Rewards accrue from the study’s escrow. Every read is logged.
- Narrowed
Untick a field; the lab’s key drops it next block.
- Revoked or expired
Access and rewards end. Computed aggregates stay.
What keeps the exchange honest
Nullifiers
Stop a second enrolment without knowing who you are. Two studies can’t link you.
Minimum cohort size
Counts are rounded to 10 and hidden below the council’s threshold.
Audit trail
Every proof, consent, read and payment is logged with its block.
The council
Contributors vote on the rules anonymously: one member, one vote.
Built around the principles, not claiming the certificate
- Minimisation
- Eligibility is one bit; fields are shared only when named.
- Specific consent
- One slip per study, listing fields and an end date.
- Withdrawal
- Revocation is one signature and takes effect on-chain.
- Accountability
- An append-only audit trail anyone involved can read.
This demo is not certified under HIPAA, GDPR or Law 25, and is not legal advice.
The contract surface, and where the demo fakes it
The simulated layer in src/lib/demo mirrors the calls a real deployment makes.
Show the contract interface
interface ICuraConsent {
/// Verify an eligibility proof and record a consent slip.
function enrol(
bytes32 studyId,
bytes calldata proof, // 256 bytes, Groth16
bytes32 nullifier, // hash(vaultKey, studyId)
uint16 fieldMask, // fields the slip covers
uint64 expiresAt
) external returns (bytes32 consentId);
function narrow(bytes32 consentId, uint16 fieldMask) external;
function revoke(bytes32 consentId) external;
function claim(bytes32[] calldata consentIds) external;
event Enrolled(bytes32 indexed studyId, bytes32 consentId, bytes32 nullifier);
event Revoked(bytes32 indexed consentId, uint64 atBlock);
}Demo module → real counterpart
prover.tsCircuit compiled to WASM, proving in a Web Worker
chain.tswagmi writeContract + waitForTransactionReceipt
store.tsContract events indexed by a subgraph
population.tsAggregated, noise-added cohort counts