Skip to Content
CryptographyCryptography
  • Article
  • Open Access

9 September 2026

35 Pages

Privacy-Preserving Health Insurance Eligibility Verification on Blockchain Using zk-SNARKs

and
1
Faculty of Science and Industrial Technology, Prince of Songkla University, Surat Thani Campus, Surat Thani 84000, Thailand
2
College of Computing, Prince of Songkla University, Phuket Campus, Phuket 83120, Thailand
*
Author to whom correspondence should be addressed.
This article belongs to the Section Blockchain Security

Abstract

Verifying a patient’s eligibility for insurance reimbursement typically requires disclosing sensitive clinical data—diagnosis codes, laboratory values, and policy details—to third parties, conflicting with the data-minimization principle of modern data-protection regimes. Blockchain platforms improve auditability but, when health records are placed on-chain, amplify the privacy problem. This paper presents a zero-knowledge framework in which a patient proves that an authority-signed health record satisfies a set of policy predicates—a covered diagnosis, a laboratory value within an approved range, and a claim amount within the policy ceiling—without revealing the underlying values. Records are committed to an on-chain Merkle registry, and a record-bound nullifier prevents double claims without linking a claim to the patient. We state the NP relation proved by the circuit and reduce claim soundness, claim unlinkability, and front-running resistance to the knowledge soundness and zero-knowledge of the argument, the collision resistance of the hash, and the unforgeability of the signature scheme. A circom and snarkjs prototype with a Solidity verifier compiles to 10,050 R1CS constraints, of which the eligibility predicates contribute only 2.1%, and produces a constant 256-byte proof verified on-chain by a fixed four-pair check. On-chain cost scales with the number of public inputs rather than circuit size, and we identify the attack surface such designs commonly leave open—proof front-running, issuer-side linkability, and anonymity-set size, which the registry population bounds rather than tree depth.

1. Introduction

Verifying a patient’s eligibility for insurance reimbursement or subsidized care usually requires disclosing sensitive clinical information to one or more third parties. Such disclosure conflicts with the data-minimization principle embodied in modern data-protection regimes: Article 5(1)(c) of the EU General Data Protection Regulation (GDPR) [1], the “minimum necessary” standard of the US Health Insurance Portability and Accountability Act (HIPAA) [2], and—in the jurisdiction that motivates our prototype—Thailand’s Personal Data Protection Act (PDPA, B.E. 2562) [3], whose Sections 24 and 26 treat health data as a special category requiring explicit consent. At the same time, institutions increasingly adopt blockchain platforms to make eligibility decisions auditable and tamper-evident [4]. The naive combination of the two—placing health records on a public ledger—amplifies rather than resolves the privacy problem.
Zero-knowledge proofs (ZKPs) offer a principled way to reconcile these competing requirements. A ZKP lets a prover convince a verifier that a statement is true while revealing nothing beyond the statement’s validity [5]. Succinct non-interactive arguments of knowledge (zk-SNARKs) add constant-size proofs and fast verification, making on-chain verification economically feasible [6]. Applied to reimbursement, a ZKP allows a patient to prove that an authority-issued record satisfies a set of policy predicates without revealing diagnosis codes, laboratory values, or policy tiers.
Existing privacy-preserving healthcare systems on blockchain largely emphasize access control and encrypted data sharing, in which confidentiality depends on key management and the data remain intelligible to authorized parties [7,8]. Where ZKPs have been applied to health data, the focus has typically been on identity proofs or single attributes [9,10]. Comparatively little work provides an end-to-end, empirically evaluated treatment of multi-predicate eligibility verification—combining set membership, range, and ceiling checks over authority-signed records—together with an analysis of on-chain cost and scalability.
This paper addresses that gap. We design a zk-SNARK circuit that verifies claim eligibility over health records signed by an issuing authority and committed to an on-chain Merkle registry [11]. A nullifier construction prevents a record from being reused for double claims without linking the claim to the patient’s identity. We implement the system with an open, reproducible toolchain and evaluate its performance as the registry and predicate set grow.
  The main contributions of this work are as follows.
  • A protocol. Authority-signed health records are committed to an on-chain Merkle registry and claimed through a zk-SNARK circuit that enforces several eligibility predicates at once, with a record-bound nullifier preventing double claims (Figure 1 and Figure 2).
  • A security analysis. We state the NP relation the circuit proves and reduce claim soundness, claim unlinkability, and front-running resistance to standard assumptions on the argument system, hash, and signature scheme (Section 3.7). The unlinkability bound is given both in the random oracle model and, for a reader declining that heuristic, under the weaker keyed-unpredictability assumption alone, and is accompanied by a quantitative model of how the anonymity set erodes across successive claim rounds, and of which erosion mechanisms are real (Section 3.7.5).
  • A positioning against prior work. We locate the result against the closest existing systems, whose primitives we share but whose composition and evaluation depth we do not (Section 2.6).
  • A disclosure analysis. A diabetes-care scenario makes explicit which values are revealed, to whom, and at which protocol step (Section 3.8).
  • A measured implementation. A reproducible circom [12] and snarkjs [13] prototype, with a Solidity verifier and registry contract, supports an evaluation of circuit complexity, prover and verifier cost, scalability, and on-chain gas, including a functional check that double claims are rejected (Section 4).
Figure 1. Protocol phases and their mapping to the empirical evaluation.
Figure 2. System architecture and the four protocol messages.
One caution belongs here rather than in the security analysis, because it is the property of such systems most easily misread. The anonymity a claim enjoys is the number of registry records consistent with its public statement, not the capacity 2 d of the Merkle tree that holds them. A depth-24 registry containing a hundred records hides a claim among at most a hundred candidates, and that pool shrinks with every record an adversary manages to tie to a claim of its own—by corrupting the patient, or by observing the network. Section 3.7.5 makes this quantitative, separates it from a plausible but incorrect reading under which elapsed claims alone erode anonymity, and derives the population a deployment must sustain to hold a target anonymity level; we state it in the introduction so that no reader carries the opposite intuition into the evaluation.
The remainder of the paper is organized as follows. Section 2 reviews related work. Section 3 presents the threat model, system design, circuit construction, security analysis, and the application scenario. Section 4 reports the experimental evaluation. Section 5 concludes and outlines future work.

2. Related Work

2.1. Zero-Knowledge Proof Systems and Tooling

Modern succinct proof systems differ along axes that directly shape applied deployments: proof size, prover and verifier cost, the need for a trusted setup, and post-quantum security. Pairing-based zk-SNARKs achieve constant-size proofs and constant-time verification but require a per-circuit trusted setup [6]. Universal and updatable setups relax this requirement, letting a single ceremony serve many circuits at some cost in proof size or prover time [14]. Transparent systems remove the trusted setup entirely: Bulletproofs offer short logarithmic proofs without a setup but with linear verification [15], while STARKs provide transparency and plausible post-quantum security at the cost of larger proofs [16]. Code-based constructions pursue post-quantum security by a different route: Wang [17] gives an MPC-in-the-Head zero-knowledge proof for rank syndrome decoding, avoiding number-theoretic assumptions altogether at the cost of proofs far too large for on-chain verification at present. On the tooling side, domain-specific languages such as circom [12] compile high-level circuit descriptions to rank-1 constraint systems (R1CS) and integrate with proving backends such as snarkjs [13]. We adopt Groth16 as the primary system for its minimal proof size and inexpensive on-chain verification, and quantify the cost of a universal-setup alternative (PLONK) on our circuit. We note that Groth16 is proved knowledge-sound but is not simulation-extractable: proofs are malleable, so a deployment must obtain non-malleability from the surrounding protocol (as ours does, by binding public inputs to on-chain state and consuming a nullifier) or adopt a simulation-extractable variant [18,19]. This distinction is frequently elided in applied work and is discussed in Section 3.7.

2.2. Zero-Knowledge Proofs on Blockchain

ZKPs have become a core privacy primitive for blockchain systems [20]. Private-payment protocols use zk-SNARKs to hide transaction graphs while preserving verifiability [21]. Anonymous-signaling frameworks introduce the nullifier pattern to prevent double actions without deanonymizing participants [22]. A long line of work on anonymous credentials enables holders to prove attribute predicates without revealing the attributes themselves [23], a capability now standardized for the web as selective disclosure over W3C Verifiable Credentials [24]. Our eligibility circuit builds on the Merkle-membership and nullifier techniques established in this literature, extending them with the domain-specific predicate set required for claim verification.

2.3. Privacy-Preserving Healthcare Data on Blockchain

Blockchain-based healthcare systems commonly combine on-chain access control with off-chain (possibly encrypted) storage, so that confidentiality rests on encryption and authorization rather than on non-disclosure. MedRec manages record access permissions through smart contracts [7], and Ancile adds proxy re-encryption for interoperable, patient-centric access control [8]; a broader landscape is surveyed in [4]. Interoperability across independent ledgers is a related concern: Sallabi [25] federates separate Hyperledger Fabric networks through global smart contracts so that records can be shared between them, which addresses where a record can travel rather than what a verifier must be shown about it. Closer to our setting, Health-zkIDM applies ZKPs to healthcare identity verification on a permissioned ledger [9], and Sharma et al. combine ZKPs with proxy re-encryption for interoperable record sharing [10]; the broader design space of ZKP-based identity sharing is surveyed in [26]. These systems prove who a party is or protect data in transit; they do not verify predicates over the record contents themselves.

2.4. Learning-Optimized Blockchain Data Sharing in UAV and Vehicular Rescue Networks

A parallel line of work secures data sharing in mobile, intermittently connected rescue networks and optimizes the resource allocation such networks require. Su et al.’s LVBS [27] builds a lightweight vehicular blockchain for disaster rescue, separating consensus from storage so that resource-poor vehicles can participate, and governing who may read which record through on-chain authorization. Wang et al. [28] extend the setting to UAV-assisted rescue: a lightweight blockchain with a reputation-based consensus logs misbehaving entities, vehicular fog nodes absorb computation the UAVs cannot carry, and a two-tier deep reinforcement-learning algorithm selects payment and resource-allocation strategies when the network parameters are unknown, with the UAV–vehicle task allocation formulated as a Stackelberg game.
Both systems are more mature than our prototype on axes we do not address at all: they operate under mobility, partition, and adversarial participation, and they optimize a genuine allocation problem that our setting does not present. The comparison that matters is what each system’s privacy guarantee is made of. In both, a record’s confidentiality rests on authorization and on the reputation machinery that polices it—the parties that need the data receive the data, and privacy is the claim that no one else does. Ours rests on non-disclosure: the party that adjudicates the claim never receives the record, and the guarantee is a reduction to stated assumptions (Section 3.7) rather than a policy that a curious or compromised authorized node can quietly violate. Neither approach subsumes the other, and the reason is structural. A rescue network must move bulk sensor and situational data between parties that genuinely need to read it, which is an access-control problem and cannot be reduced to a predicate proof; an eligibility decision needs only a Boolean, which is exactly why it can be settled without disclosure. The learning-based optimization of [28] is orthogonal to our cost question for the same reason: it allocates scarce bandwidth and computation across a fleet, whereas the cost we measure is a fixed per-claim verification price set by the public-input count (Section 4.5) that no scheduling policy can reduce. We include both systems in the design comparison of Section 2.6 for completeness; neither employs a proof system, so, like MedRec and Ancile, neither appears in the evaluation comparison there.

2.5. Zero-Knowledge Proofs for Insurance Claims and Health Data Sharing

A smaller body of work targets the claim and data-sharing problems directly, and it is against this work that our contribution must be judged. Zheng et al. [29] give the earliest scheme we are aware of for privacy-preserving insurance claims, combining a Schnorr-based non-interactive proof with homomorphic encryption under the DBDH assumption; the construction is interactive-protocol–derived rather than succinct, and no on-chain cost is reported. Qiu et al. [30] apply ZoKrates-generated proofs to car insurance, separating private and public smart contracts for policy creation and validation. In health insurance specifically, Sanober and Anwar [31] deploy a zk-SNARK claim workflow on the Polygon PoS network and report transaction cost and latency, and Bakare et al. [32] describe a Polygon-based claim architecture in which a hospital issues proofs of treatment and billing—though that work is explicitly a conceptual feasibility study rather than an implementation, as its authors state.
On the data-sharing side, Albalwy’s ZK-EHR [33] is the closest comparator methodologically: it uses a custom Groth16 circuit to enforce role-based access policy on-chain, decoupling authorization from identity disclosure, and reports 216,631 gas per verification with roughly 390 ms verification latency. A permissioned-Ethereum protocol in [34] proves validity of FHIR-formatted records with zk-SNARKs at ≈93,000 gas, and Krishappa et al. [35] secure genomic record sharing with an interactive Schnorr protocol and ECC over IPFS-backed storage, evaluated as a Python simulation (version not reported by its authors) rather than on an EVM.
A third group applies zk-SNARKs to electronic health records themselves. Anusuya et al. [36] pair a decentralized EHR store with a non-interactive zero-knowledge authentication scheme light enough for resource-constrained medical devices, and Luong and Park [37] use zk-SNARKs to authenticate IoT healthcare data flowing from sensors through gateways to service providers while keeping the originating user anonymous. Alahmari et al. [38] combine smart contracts, decentralized storage, and encryption to give patients control over record sharing, with privacy resting on access control rather than on non-disclosure proofs. The distinction that matters for our purposes is uniform across all three: the proof establishes who the party is, or that they are entitled to reach a record, whereas ours establishes what the record says, without revealing it. That difference determines what can be automated. An authentication proof still requires the record to be handed to whoever decides the claim; a predicate proof does not.

2.6. Positioning

Table 1 compares the systems above along the axes that distinguish them. Two observations follow.
Table 1. Comparison with the closest prior work.
First, no single novel mechanism is claimed here. Merkle-membership proofs, nullifiers, in-circuit EdDSA, and Groth16 verification on the EVM are all established primitives, and a contribution that rested on any one of them would not be defensible. What the table shows is that the combination has not been assembled before for this problem. The Statement proved column is the discriminating one. Prior systems prove identity, device or user authentication, or entitlement to reach a record [9,10,33,36,37,38]; others prove claim validity without binding the record to an issuer signature inside the circuit [29,34]; one stops at a conceptual design [32]. To the best of our knowledge, none of the systems in Table 1 proves a predicate over the contents of an authority-signed record, and none combines that with registry membership and a record-bound nullifier in a single statement. The practical consequence is that in every prior system the record must still be disclosed to whichever party adjudicates, so the disclosure the patient wanted to avoid merely moves one step later in the workflow.
Second, the axes on which such systems should be compared are not the ones on which a comparison is easiest to win. Whether a paper happens to report a constraint breakdown or a scalability study says more about its authors’ reporting choices than about the system they built. Table 2 therefore records the evaluation setting and the deployment properties that follow from each system’s choice of proof machinery—and on almost all of them our construction is unremarkable. It is one of six verified by a contract rather than by an off-chain party, one of several with constant-size proofs, and it carries the same per-circuit ceremony as ZK-EHR [33]. We include the table not because it favours us but because it fixes what the gas figures of Section 4.5 can and cannot be compared against.
Table 2. Evaluation setting and deployment properties of the implemented systems.
On one axis we are behind. The Schnorr-type constructions of Zheng et al. [29] and Krishappa et al. [35] need no trusted setup at all, whereas ours requires a per-circuit ceremony whose integrity rests on assumption (A1); a universal-setup system would reduce that to a single ceremony, at a cost we quantify in Section 4.4. What those two give up in exchange is on-chain verification—neither is checked by a contract, and an interactive protocol cannot be, since a passive verifier cannot issue challenges—which is the property that lets an insurer settle a claim automatically rather than adjudicate it. That is a trade rather than a deficiency on either side, and a deployment with no need for on-chain settlement should prefer the cheaper setup. The design difference we do claim is the one recorded in the Statement proved column of Table 1, not anything in Table 2.
Where we do claim to contribute is in measuring a construction whose parts are individually familiar. Section 4.3 separates authentication cost from predicate cost and finds the eligibility logic accounts for 2.1% of the circuit; Section 4.5 finds that on-chain cost tracks the public-input count rather than the constraint count. Neither is a remark about other authors’ diligence. Both are quantities obtainable only by building the system and instrumenting it, and both invert the intuition one would otherwise bring to the design: the predicates are nearly free where they were expected to be expensive, and the policy is expensive on-chain where it was expected to be free.
We therefore claim novelty in the composition and its measurement, not in the primitives: (i) composite eligibility predicates over authority-signed records, rather than identity or access-policy predicates; (ii) binding of the proof to on-chain policy and registry state, so that verification cannot be performed against forged parameters; (iii) explicit security reductions (Section 3.7); and (iv) an evaluation that separates authentication from predicate cost and reports measured gas.

3. Proposed Solution

Figure 1 summarizes the research as three protocol phases and maps each to the evidence that supports it in Section 4. Phase I (setup) compiles the circuit, runs the trusted setup, and deploys the contracts, and is evaluated by the circuit complexity of Section 4.3; Phase II (issuance) signs records and advances the on-chain root, and is evaluated by the prover scalability of Section 4.4; Phase III (claim) builds the witness, proves off-chain, and verifies on-chain, and is evaluated by the gas measurements of Section 4.5.

3.1. System Model

The system involves three entities. An issuing authority (e.g., a hospital or regulator) creates health records, signs them, and publishes a commitment to an on-chain registry. A patient acts as the prover, generating a proof locally (off-chain) from private witness data. An on-chain verifier (a smart contract) checks the proof and enforces single use. Figure 2 shows the architecture. The authority signs records and commits the registry root on-chain (messages 1 and 2); the patient generates the zk-SNARK proof off-chain and submits it together with the public inputs (message 3); the contract binds those inputs to the registered state, verifies the proof, records the nullifier, and returns the verdict (message 4). Only these four messages cross the trust boundary—no record field ever does.
Each record is encoded as a leaf commitment using the SNARK-friendly Poseidon hash [39]:
L = Poseidon c , v , pid , cc , k , k = Poseidon ( s ) ,
where c is the diagnosis code, v the laboratory value, pid the policy identifier, cc the coverage ceiling, and k the commitment to a per-record patient secret s drawn uniformly from F p . Leaves are inserted at index idx ∈ { 0 , … , 2 d − 1 } into a Merkle tree [11] of depth d whose root R is registered on-chain.
The secret s is per record, not per patient: reusing one secret across records would make all of a patient’s nullifiers derivable from a single compromised value.
Blinded issuance. A naive issuance flow, in which the authority computes L itself, gives the authority knowledge of s and hence the ability to recompute every nullifier its records will ever produce—so unlinkability would hold against the contract, the insurer, and chain observers, but not against the issuer. Because an issuer that can silently track every claim is difficult to reconcile with the data-minimization goal this work is motivated by, we specify issuance so that this capability does not arise. This is why (1) commits to k = Poseidon ( s ) rather than to s directly: the patient samples s locally and sends the authority only k, the authority signs the resulting L having verified the clinical fields it already holds, and the circuit recomputes k from the private s before recomputing L. The authority learns nothing about s beyond Poseidon ( s ) , so it cannot derive the nullifier of (8).
The circuit cost is one additional Poseidon permutation, measured at 213 constraints (Section 4.6).

3.2. Threat Model and Security Goals

3.2.1. Adversary

We consider a probabilistic polynomial-time adversary A that (i) reads all on-chain state and all mempool traffic, (ii) submits arbitrary transactions and may reorder or front-run pending ones, (iii) corrupts an arbitrary subset of patients, learning their records and secrets, and (iv) acts as the insurer, i.e. observes every verified claim. A does not corrupt the issuing authority and does not break the underlying primitives.

3.2.2. Assumptions

The assumptions are of three different kinds, and we group them accordingly rather than presenting them as a single list: (A1) constrains the setup, (A2) constrains the deployment, and (A3)–(A5) are cryptographic hardness assumptions. Only the last group is reduced to in Section 3.7; the first two are trust conditions that a deployment must establish by other means.
Setup assumption. (A1) The per-circuit Groth16 common reference string is generated by a ceremony in which at least one participant is honest and discards their toxic waste [40].
System assumptions. (A2a) The issuing authority is honest in the sense that it signs only records it has verified. Note that we do not additionally assume it refrains from deanonymizing claims: blinded issuance (Section 3.1) withholds s from it, so Proposition 2 holds against the issuer as well. (A2b) Registry injectivity: the authority inserts each leaf at exactly one index. This is a registry invariant rather than a circuit property, and it is load-bearing. The nullifier Poseidon ( s , idx ) is unique per record only because idx is; nothing in R prevents the same leaf L from being inserted at two indices, and a prover holding two valid ( path , idx ) pairs for one record would derive two distinct nullifiers and claim twice. Because s is sampled uniformly per record, accidental collisions between distinct records are negligible, so (A2b) is a constraint on issuance procedure, not on the cryptography. A deployment that cannot enforce it should bind the nullifier to L rather than to idx , at the cost of the extra hash.
Cryptographic assumptions. (A3) Poseidon over the BN254 scalar field is collision resistant [39], and  Poseidon ( s , · ) is unpredictable when keyed by a secret, uniformly sampled s: an adversary not holding s cannot distinguish Poseidon ( s , idx ) from a uniform field element. This keyed-unpredictability property is all that Proposition 2 requires. We prove that proposition in the random oracle model because it gives the cleanest bound, but we flag the modelling explicitly: treating an algebraic hash as a random oracle is a heuristic, and one deserving more caution for arithmetization-friendly designs than for the constructions the methodology was developed against. Proposition 2(b) therefore states the same result under the keyed assumption alone, with no idealized model, and Section 3.7.4 sets out the published cryptanalysis that motivates offering both. (A4) EdDSA over Baby Jubjub is EUF-CMA secure [41,42]. (A5) The discrete logarithm and q-type assumptions underlying Groth16 hold over BN254 [6]; we note that BN254 offers roughly 100 bits of security after the Kim–Barbulescu improvements to the tower number field sieve [43], which is below the 128-bit level usually targeted today and is a deployment consideration rather than a property of the construction.

3.2.3. Security Goals

Beyond the standard properties of the argument system—completeness, knowledge soundness, and zero-knowledge [5,6]—the protocol targets two protocol-level goals, formalized in Section 3.7: claim soundness (no A can obtain approval for an ineligible record, a record not signed by the authority, or a second approval for a record already claimed) and claim unlinkability (no A can associate an approved claim with the patient or record that produced it, beyond what the public inputs reveal).

3.2.4. Explicitly out of Scope

(i) Collusion by, or compromise of, the issuing authority, which by construction can forge records; note that blinded issuance (Section 3.1) removes its ability to link claims, but not its ability to mint them. (ii) Network- and timing-level metadata: a patient who proves and submits from their own IP address is trivially linkable, so a relay or mixnet is required in practice. (iii) Leakage through the public inputs themselves—most importantly the claim amount a, which together with submission time is a strong quasi-identifier when the claim population is small. (iv) Anonymity-set erosion: unlinkability is bounded by the number of plausible leaves, not by tree capacity 2 d , so a registry with few enrolled patients provides little hiding regardless of d. (v) Denial of service by an adversary who floods the contract with invalid proofs; each is rejected, but the gas market is outside our model. (vi) Compromise of the prover’s own execution environment—a malicious wallet, tampered witness-generation code, or side-channel observation during proving—all of which expose s directly. This last item deserves emphasis rather than dismissal, because it constrains deployment: a patient who delegates proving to a third-party service must hand that service the full witness, including s, which surrenders unlinkability and lets the service recompute the nullifier at will. Local proving is therefore a security requirement of this design and not merely a convenience, and it is what makes the single-vCPU proving cost of Section 4.4—2.25 s on hardware a patient plausibly owns—a property of the threat model rather than only a performance result.

3.3. Eligibility Predicates

Given public policy parameters—a covered set C and laboratory bounds [ ℓ min , ℓ max ] —and a public claim amount a, a record is eligible iff
c ∈ C ,
ℓ min ≤ v ≤ ℓ max ,
a ≤ cc .
Crucially, (4) is enforced without revealing the ceiling cc , and (2)–(3) without revealing c or v.

3.4. Circuit Construction

The circuit (artifact file health_claim_core.circom in the artifact of Section 4.2) enforces the following constraints; all cryptographic components (Poseidon, EdDSA, Merkle verification, comparators) are instantiated from the circomlib standard library [12].
  • Leaf commitment: recompute the secret commitment k = Poseidon ( s ) and then L from the private record fields by (1).
  • Recipient binding: expose the payout address rcpt as a public input and constrain it inside the circuit by the redundant quadratic relation
    rcpt 2 = rcpt sq ,
    where rcpt sq is an auxiliary signal. This is the standard anti-optimization idiom for pinning a public signal that no other constraint consumes: the relation is vacuous arithmetically but not structurally, since without it the compiler eliminates an otherwise unused public input, and with it rcpt is fixed by the proof. “Vacuous” here means unconstraining of the witness, not unconstrained— rcpt is part of the statement either way, and it is its presence in the statement, not the arithmetic of the relation, that the front-running argument uses. The contract requires rcpt = msg . sender , which is what prevents the front-running attack analysed in Section 3.7.6.
  • Authority signature: verify an EdDSA signature [41] σ = ( R σ , S ) over Baby Jubjub [42] on the message L under the authority public key A:
    S · B = R σ + H P ( R σ , A , L ) · A ,
    where B is the curve base point and H P the Poseidon-based challenge hash; the in-circuit check is cofactor-adjusted.
  • Merkle inclusion: with authentication path ( e 0 , … , e d − 1 ) and direction bits b i , first constrain each bit to be Boolean, b i ( 1 − b i ) = 0 , then apply a conditional swap followed by a single Poseidon permutation per level:
    h 0 = L , ( ℓ i , r i ) = h i + b i ( e i − h i ) , e i + b i ( h i − e i ) , h i + 1 = Poseidon ( ℓ i , r i ) ,
    and constrain h d = R against the public registered root. Writing the level as a mux-then-hash rather than as a linear combination of two hash evaluations matters for cost: (7) costs one Poseidon permutation plus the two selector products per level—242 constraints—whereas evaluating Poseidon on both orderings would cost roughly twice as much. The booleanity check adds one further constraint per level, giving the 243 per level that Section 4.1 measures for the canonical circuit. It is not optional: MultiMux1 interpolates its selector rather than constraining it, so without the explicit check a malicious prover can choose b i ∉ { 0 , 1 } and reach an arbitrary root. The 242 quoted in Section 4.4 is the primary campaign’s figure, measured before this constraint was present.
  • Predicates: enforce (2)–(4) via fixed-width (64-bit) comparators and an equality-sum set-membership gadget. The comparators additionally range-constrain their operands to 64 bits, which is what prevents the field-wraparound attack that a naive “ v − ℓ min is non-negative” encoding would admit over F p ; the policy parameters must therefore be enforced on-chain to lie below 2 64 .
  • Nullifier: expose
    nf = Poseidon ( s , idx ) , idx = ∑ i = 0 d − 1 b i 2 i ,
    as a public output, where idx is the leaf index recovered from the already-Boolean-constrained path direction bits. Because the recovery of idx is a linear combination of existing signals it adds no R1CS constraints. Because s is secret and uniform, nf is unlinkable to the patient; because idx is pinned by the same path that proves membership, nf is a deterministic function of the specific record being claimed, so any second claim on that record reproduces the same nullifier and is rejected by the contract (Section 3.5).
    Binding the nullifier to the record rather than to a prover-chosen claim identifier is essential. Deriving nf = Poseidon ( s , cid ) from a free claim identifier cid —an encoding that appears in several applied descriptions of this pattern—does not restrict reuse at all: an adversary simply re-proves the same record under a fresh cid and obtains a fresh, unused nullifier. It also introduces spurious collisions in the other direction, since two distinct records sharing a secret would collide under a common cid .

3.5. On-Chain Protocol

The smart contract stores the registered Merkle root, the authority public key, and the canonical policy parameters. On claim submission it (i) checks that the proof’s public inputs match the registered state, preventing proofs against forged policies; (ii) checks that the nullifier is unused; (iii) verifies the proof; and (iv) records the nullifier and approves the claim. This binding of the proof to on-chain state is essential: without it, a prover could satisfy the circuit against parameters of their own choosing.
Two deployment details follow from this design and are not optional. First, because step (i) compares against a single stored root, any issuance that advances the root invalidates every proof already in flight against the previous root. A production contract must therefore retain a bounded window of recent roots—we use a 32-entry ring buffer in the prototype—and accept a proof whose root lies anywhere in that window, trading a bounded staleness against liveness. Second, cross-deployment replay must be prevented, and doing so correctly requires care about where the domain separator lives. A chain identifier and verifier address held only as contract constants do not suffice: the proof itself remains valid under any deployment sharing the verification key, and only the per-contract nullifier set differs, so the same proof can be replayed against a sibling deployment and consume a fresh nullifier there. Genuine cross-deployment non-replayability requires the separator to be a public input—part of the statement x, and therefore fixed by the proof, exactly as rcpt is in (5). The prototype evaluated in Section 4.3, Section 4.4, Section 4.5, Section 4.6, Section 4.7 and Section 4.8 does not implement this: the registry contract those measurements were taken against pins the policy and the authority key but carries no domain separator, so its proofs are deployment-agnostic. The artifact now ships the repair, and we give the analysis, the code and the measured cost rather than recording a to-do.

3.5.1. What the Omission Does and Does Not Break

The gap is narrower than it first appears, and its shape is worth stating exactly. A cross-deployment replay requires a sibling deployment that (i) shares the verification key, hence the identical circuit, and (ii) has registered the same root, the same authority key A, and the same policy ( C , ℓ min , ℓ max ) —because submitClaim compares every one of those against its own storage before verifying. A sibling differing in any of them rejects the proof already. The exposure is therefore confined to deliberate clones of one registry: a testnet mirror, a staging contract, or a second chain running the same policy over the same patient population.
Within the single-deployment model in which Propositions 1 and 2 are stated, neither is affected. Claim soundness is untouched, because a replayed proof still attests to an authority-signed, eligible, registered record and consumes a nullifier in the deployment that accepts it; and unlinkability is untouched, because the replay reveals nothing the original claim did not. What fails is the global single-use property that spans deployments: across m clones one record can be paid m times, once per nullifier set, so a deployment operating exactly one registry per policy already meets its stated goals, while a deployment that mirrors a registry must apply the fix below or accept an m-fold double-claim exposure. We state the guarantee at this granularity rather than claiming replay resistance without qualification.

3.5.2. The Fix and Its Price

The repair is two additions and we give them concretely. In the circuit, the separator is declared public and pinned by the same anti-optimization idiom that fixes rcpt :
  signal input dsep;   // public, 17th signal
  signal dsepSq;  dsepSq <== dsep * dsep;
and in the registry contract it is derived once at deployment and compared on every claim:
  uint256 public immutable DSEP;
  constructor(...) {
      DSEP = uint256(keccak256(abi.encode(
	  block.chainid, address(this)))) % r;
  }
  // inside submitClaim, beside the existing policy checks:
  require(pub[16] == DSEP, "domain mismatch");
where r is the BN254 scalar-field modulus. Because DSEP is derived from the chain identifier and the contract’s own address, no two deployments share it; and because dsep belongs to x, it is fixed by the proof, so an adversary cannot re-target a proof without producing a new one—which is the argument of Proposition 3 applied to a different public signal. Declaring DSEP immutable rather than storing it keeps the registry-side check free of a cold SLOAD: the value is inlined into the bytecode as a PUSH32, so the comparison costs a handful of gas.
The price is one R1CS constraint and one public input, and both are now measured rather than modelled. In circuit, the separator costs exactly one constraint—the pin above—taking the canonical circuit at depth 20 from 10,050 to 10,051, the same unit cost as the recipient binding. On chain, the artifact’s scripts/dsep_bench.js measures the 16- and 17-signal configurations in a single process, so the two rows differ in exactly one public signal and nothing else: verifyProof rises by 7135 gas and submitClaim by 7172 gas. Transferring those increments onto the canonical rows measured in Section 4.5 gives ≈327,100 gas for verification and ≈382,100 gas for a domain-separated claim, an increase of 1.9%.
Two details of the measurement are worth stating, because both bear on how such numbers should be read. The harness draws its public signals from the depth-20 test vector of scripts/build_input.js rather than from convenient small constants: calldata is charged at 16 gas per non-zero byte and 4 per zero byte, and a harness fed dummy values understates verifier gas by well over a thousand. So calibrated, it reproduces the 16-signal rows of Section 4.5 to within 60 gas, or 0.02%—the residual being the run-to-run variation in the number of zero bytes in a randomized Groth16 proof, not a systematic offset. And the measured 7172 exceeds the ≈6970 that transferring the recipient-binding increment of Section 4.6 would predict, by 202 gas or 2.9%. The reason is calldata and is worth recording: rcpt is a 20-byte address left-padded with twelve zero bytes, costing 20 × 16 + 12 × 4 = 368  gas, whereas dsep is a full-entropy 32-byte field element costing 32 × 16 = 512 . A public input’s price therefore depends on what is in it, not only on how many there are—a second-order effect that the per-input figures of Section 4.5 average over, and a caution against transferring an increment across signals of different shape.
The functional check is the one that matters for Section 3.5.1: scripts/reasons.js ds deploys a sibling registry with the same verifier, the same policy and the same registered root but a different address, and hence a different DSEP. It rejects a proof built for the first deployment with domain mismatch, where without the separator it accepts and consumes a fresh nullifier. The gap in the implementation is therefore closed, not merely priced.

3.6. Loss and Re-Issuance of the Record Secret

Section 3.2 places compromise of the prover’s execution environment out of scope. Loss of that environment is a different matter and is not an attack at all, but it has a consequence the design must answer for, because it follows directly from the property that makes the design work.
If a patient loses s, the record becomes permanently unclaimable. The circuit needs s to recompute k = Poseidon ( s ) and hence the leaf L, and to derive the nullifier of (8); no on-chain data helps, because the registry stores only L, which commits to s through a one-way hash. This is the same fact as Proposition 2 read in the other direction: a system in which the operator can recover s is a system in which the operator can link every claim that record will ever produce. There is no recovery mechanism that preserves the stated security goals, and we propose none.
Re-issuance, and why revocation is the hard part. The sound response is re-issuance rather than recovery. The patient samples a fresh s ′ , sends k ′ = Poseidon ( s ′ ) to the authority, and the authority re-signs the same clinical fields into a new leaf L ′ at a new index. The subtlety is what becomes of the old leaf. Leaving it in the tree lets the record be claimed twice should s ever resurface—exactly the failure that (A2b) is written to exclude—and the authority cannot pre-burn the old nullifier, because blinded issuance denies it s. Issuer-side revocation is therefore impossible by construction, and we record this as a cost of blinded issuance that Section 3.1 did not previously state. What the authority can do is rebuild the tree without the lost leaf and advance the root. Because membership is proved against a registered root and the contract accepts only the 32 most recent (Section 3.5), the old leaf becomes unclaimable once the ring buffer has rolled past every root that contained it. The cost is one root update— 47,178  gas, from Section 4.5—plus a bounded staleness window, and the operational requirement is that re-issuance be rare relative to the buffer’s turnover, which it is: re-issuance is a lost-key event, whereas root updates are a routine batching operation. A deployment expecting frequent loss should widen the buffer rather than shorten the window.
Reducing the loss rate without weakening the model. A deployment can make loss much less likely without touching the circuit at all, by deriving record secrets deterministically from a single backed-up seed, s j = Poseidon ( seed , j ) for the patient’s j-th record, so that one recoverable seed regenerates every record secret. Nothing in-circuit changes: s j remains a private input, and under (A3) it is unpredictable—hence uniform, to any party without the seed—and, critically, the  s j remain individually unpredictable from one another, so the objection of Section 3.1 to a per-patient secret does not apply. What a seed does concentrate is the consequence of compromise: an adversary holding seed derives every nullifier the patient will ever produce, whereas an adversary holding one s j learns one record. Since environment compromise is already out of scope (Section 3.2) while key loss is a routine event with no adversary behind it, we regard this as the right trade for most deployments, and state it as a deployment option rather than as part of R .

3.7. Security Analysis

3.7.1. The Relation

Let Π = ( Setup , Prove , Verify ) be a non-interactive argument for the relation R below, instantiated with Groth16 [6]. Write the statement (public input) and the witness as
x = ( R , nf , a , A , ℓ min , ℓ max , C , rcpt ) , w = ( c , v , pid , cc , s , σ , { e i } i < d , { b i } i < d ) .
Definition 1
(Eligibility relation).  ( x , w ) ∈ R if and only if all of the following hold:
(R1) 
L = Poseidon ( c , v , pid , cc , Poseidon ( s ) ) ;
(R2) 
EdDSA . Verify ( A , L , σ ) = 1 , as in (6);
(R3) 
b i ( 1 − b i ) = 0 for all i < d , and the recursion (7) on ( L , { e i } , { b i } ) yields h d = R ;
(R4) 
c ∈ C , ℓ min ≤ v ≤ ℓ max , and  a ≤ cc , with  v , a , cc < 2 64 ;
(R5) 
nf = Poseidon s , ∑ i b i 2 i ;
(R6) 
rcpt is constrained by (5), fixing it as part of the statement.
The circuit of Section 3.4 is an R1CS encoding of exactly R ; the on-chain contract accepts a claim iff Verify ( vk , x , π ) = 1 , the components of x other than nf equal the registered state, and  nf ∉ N .

3.7.2. Claim Soundness

Proposition 1
(Claim soundness). Under assumptions (A1), (A3), (A4), and (A5) of Section 3.2, no PPT adversary A obtains an approved claim that is not attributable to a distinct, authority-signed, eligible record in the registry, except with probability negl ( λ ) = ϵ ks + ϵ cr + ϵ euf , where the three terms bound the knowledge-soundness error of Π , the collision probability of Poseidon, and the EUF-CMA advantage against EdDSA, respectively.
Proof. 
Suppose A produces ( x ∗ , π ∗ ) that the contract accepts. By knowledge soundness of Π there is an extractor E that, given A ’s coins, outputs w ∗ with ( x ∗ , w ∗ ) ∈ R , except with probability ϵ ks . We consider the three ways a claim could be illegitimate. (a) Forged eligibility: by (R4) the extracted witness satisfies the predicates, and by (R1) and (R3) it is the same witness that produces the leaf and the root, so a claim approved for an ineligible record yields a Poseidon collision, bounded by ϵ cr . (b) Unregistered record: (R2) forces a valid EdDSA signature under the registered key A on L; since the contract pins A, an L never signed by the authority yields an EUF-CMA forgery, bounded by ϵ euf . Note that (R3) alone would not suffice, because the root is a public value the adversary can observe but the signature check is what ties the leaf to the authority. (c) Double claim: by (R5) the nullifier is Poseidon ( s , idx ) , and by (R3) with the booleanity constraints the bits { b i } are uniquely determined by the accepting path, so idx is fixed by the record claimed. Two accepted claims on the same record therefore carry the same nf unless Poseidon collides, and the second is rejected by the nf ∉ N check.    □
Case (c) is precisely where the construction is sensitive to the encoding of the nullifier: had nf been derived from a prover-chosen claim identifier, idx would not appear in the extracted witness and the argument would fail, since nothing would force two claims on one record to collide. Note also that Groth16 proofs are malleable [18]: given π = ( A π , B π , C π ) an adversary can produce a distinct proof for the same statement. This does not affect Proposition 1, because acceptance is governed by the statement (and hence by nf ) rather than by proof equality; a deployment that keyed replay protection on proof bytes instead of on the nullifier would be broken. Where simulation extractability is required for composition, the variants of [18,19] apply at modest additional verification cost.

3.7.3. Claim Unlinkability

Proposition 2
(Claim unlinkability). Let S be the set of registry leaves consistent with the public statement x. Under (A1), (A2), (A3), and the zero-knowledge property of Π , the view of any PPT adversary given an accepted claim is computationally independent of which element of S produced it, with distinguishing advantage at most
(a) 
ϵ zk + q H / | F p |   +   1 / | S | , modelling Poseidon as a random oracle to which A makes at most q H queries; or
(b) 
ϵ zk + Adv Poseidon unp ( A ) + 1 / | S | , assuming only the keyed unpredictability of (A3) and no idealized model, where Adv Poseidon unp ( A ) is A ’s advantage in distinguishing Poseidon ( s , idx ) from a uniform element of F p given Poseidon ( s ) , for uniform secret s and idx of A ’s choosing.
Proof sketch. 
The adversary’s view consists of π , x, and the transaction envelope. By zero-knowledge, π is simulatable from x alone, contributing ϵ zk . Within x, all components except nf are public constants of the deployment, save rcpt , which the patient chooses and which we assume is a fresh address. It remains to argue that nf leaks nothing. Modelling Poseidon as a random oracle (A3), nf = Poseidon ( s , idx ) is uniform on F p and independent of idx unless A queries the oracle at a point whose first argument is s. Since s is drawn uniformly from F p and is never published—the registry stores only the leaf L, which commits to k = Poseidon ( s ) —each of A ’s q H queries hits s with probability 1 / | F p | , so the union bound gives q H / | F p | . Conditioned on no such query, nf is distributed identically for every leaf in S and therefore carries no information about which one produced it. Blinded issuance is what extends this to the issuing authority: it holds only k = Poseidon ( s ) , so recovering s—and hence nf —requires inverting the oracle, an event already accounted for above. The residual 1 / | S | is the guessing advantage within the anonymity set.
Bound (b). The argument above invokes the random oracle exactly twice: to assert that nf is uniform on F p and independent of idx , and to assert that the issuer cannot invert k = Poseidon ( s ) to recover s. Both are instances of a single statement—that A , given Poseidon ( s ) , cannot distinguish Poseidon ( s , · ) from a random function on the one point it observes—which is precisely the keyed unpredictability of (A3). Replacing the union bound q H / | F p | by Adv Poseidon unp ( A ) therefore yields the same conclusion with no idealized model, at the price of leaving that term as a concrete assumption about Poseidon rather than as a counting argument.    □
Proposition 2 makes the operative limitation explicit: privacy is bounded by | S | , not by tree depth. Because x publishes the claim amount a, S is restricted to leaves whose ceiling admits a, and a distinctive amount can collapse S to a single leaf. Deployments should therefore quantize claim amounts into coarse buckets, and should not report depth-24 capacity as though it were an anonymity guarantee. Section 3.7.5 quantifies how | S | behaves once the registry has been used for a while, which is the regime a deployment actually operates in.

3.7.4. On Modelling Poseidon as a Random Oracle

Because Proposition 2(a) is the only claim in this paper that invokes an idealized model, and because we would rather a reader could audit the heuristic than be asked to accept it, we state what the published cryptanalysis of Poseidon says and what the proposition costs if the heuristic is refused.
What is known about Poseidon. Poseidon’s round counts are set by a security argument against statistical and algebraic attacks [39], and that argument has been probed steadily since publication. Beyne et al. [44] introduced cryptanalytic techniques aimed specifically at the low-degree, algebraically structured primitives that proof systems favour, and applied them to reduced-round members of this family. Bariant et al. [45] showed that two full rounds can be shaved from such substitution–permutation constructions at little cost, and combined this with univariate and multivariate root-finding to solve several of the Ethereum Foundation’s cryptanalysis challenges; those targets are round-reduced by construction, so the result bounds the security margin rather than breaking a deployed instance. Ashur et al. [46] revisited the HADES strategy underlying both Poseidon and Poseidon2 and went further: using the designers’ own round-number script, they exhibit a full-round parameter set claiming 1024 bits of security whose Gröbner-basis attack complexity is bounded by 2 731.77 , and they show that the original security argument stops holding at claimed security levels as low as 384 bits. We state this plainly rather than softening it: it is a break of a claimed bound on a full-round instance, not merely an improved attack on a reduced-round one. Three qualifications bear on our use. It is a violation of a claimed bound rather than a computationally feasible attack, 2 731.77 being far beyond reach. It is confined to non-standard security levels—the authors state they are “not aware of any practical instance directly affected”—and their worked cases are 1024-, 512- and 384-bit instances over a 128-bit field, the opposite corner of the parameter space from the 128-bit-security Poseidon over the 254-bit BN254 scalar field that circomlib instantiates and our circuit uses. And no λ = 128 instance is analysed at all, which is an absence of evidence rather than a certification; we do not present it as one. The state of the art is a security argument under active revision, not a broken primitive, which is a reason to state our assumption precisely rather than a reason to abandon the hash.
What the heuristic costs. The exposure is narrower than the general caution suggests. Nothing in claim soundness uses the random oracle: Proposition 1 needs only collision resistance of Poseidon and EUF-CMA security of EdDSA, so an algebraic distinguisher that separates Poseidon from a random oracle without yielding collisions leaves soundness entirely untouched. Unlinkability is the only property at stake, and it needs far less than a random oracle: as Proposition 2(b) records, the whole argument goes through under keyed unpredictability on a single point. The random oracle model is what lets us write the concrete q H / | F p | in place of Adv Poseidon unp ( A ) ; a reader who declines the heuristic loses a number, not a guarantee. This is also why the choice is not load-bearing for deployment: should future cryptanalysis erode confidence in Poseidon’s pseudorandomness, the response is to re-instantiate the nullifier hash—a single Poseidon permutation, some 240 of the circuit’s 10,050 constraints by the per-level accounting of Section 3.4—without touching the relation, the contract, or either soundness proof.

3.7.5. Anonymity-Set Evolution over Multiple Claim Rounds

Proposition 2 bounds a single claim. Because  | S | is not a constant of the deployment but a quantity the deployment consumes, that bound is optimistic in a way that matters operationally, and we make the erosion quantitative here.
Fix a registry holding N records at the moment a claim is submitted, and write q ( a ) for the fraction of those records whose hidden ceiling admits the public amount a. Two public quantities discriminate between leaves. The amount a restricts S to the compatible sub-population, of expected size q ( a ) N ; and the root R restricts it to leaves present in the tree at the version proved against, so a claim settled against an older root in the 32-entry window (Section 3.5) hides only among the records enrolled by then. The remaining components of x are constants of the deployment, and  rcpt is assumed fresh.
One tempting inference does not hold, and we state it first because getting it wrong overstates the erosion. It is natural to reason that after T accepted claims only N − T records remain live, so the anonymity set has shrunk to q ( a ) ( N − T ) . It has not. Single use means the map from claims to records is an injection, but the adversary does not observe that map: under an exchangeable arrival model the assignment of records to the T + 1 published nullifiers is a uniformly random injection, so the marginal posterior for any one claim remains uniform over the whole compatible population. Elapsed claims alone therefore do not reduce | S | for a target claim. What reduces it is attribution: a record that the adversary has already tied to some claim is one it can strike off for every other.
Attribution accumulates, and the threat model supplies it. The adversary of Section 3.2 corrupts an arbitrary subset of patients and learns their secrets, hence computes their nullifiers and recognizes their claims exactly; Section 3.2 additionally lists network metadata as an out-of-scope but real channel by which further claims become attributable. Writing K for the number of registry records the adversary has attributed by either route, and  S K for the anonymity set of a claim by an unattributed patient,
E | S K | ≈ q ( a ) N − K + 1 .
The additive 1 is the claiming record itself, which is always a member of its own anonymity set, so (9) degrades to the correct endpoint | S N − 1 | = 1 : once every other record is attributed, the remaining claim is identified exactly, whatever d is. The quantity that governs privacy over a deployment’s life is thus the corrupted-and-observed fraction K / N , not the elapsed claim count—a distinction that matters operationally, because K is something an operator can bound by vetting participants and mandating a relay, whereas T grows unavoidably with use.
A second leak needs no attribution at all. Suppose the compatible class for amount a has m members and m claims at that amount have been accepted. Single use then forces every member of the class to have claimed. Nullifier unlinkability still hides which nullifier belongs to whom, but the question “has this patient claimed?” is answered for the entire class, and answered by counting alone. Exhaustible classes therefore leak participation even when they do not leak identity, and coarse amount buckets mitigate this for the same reason they raise q ( a ) .
Table 3 evaluates (9). The instructive comparison runs across rows rather than along them. Enlarging the registry buys anonymity linearly, but attribution destroys it linearly too: at K / N = 0.9 a registry of ten thousand records facing a moderately distinctive claim amount ( q = 0.1 ) offers exactly the 101-record anonymity set of an unattributed registry one-tenth its size. Depth appears nowhere in the table, which is the point.
Table 3. Expected anonymity set E [ | S K | ] from (9), by registry size N, the fraction q of the registry whose ceiling admits the public claim amount, and the share K / N of the registry the adversary has already attributed—through patient corruption, network metadata, or class exhaustion. Values are rounded down to whole records.
Two design rules follow, and both are arithmetic rather than advice. First, quantize aggressively: q ( a ) is fixed by how many distinct claim amounts a policy admits, and it enters (9) multiplicatively, so halving the number of amount buckets doubles every anonymity set in the deployment at no cryptographic cost and no gas cost—and, by the class argument above, makes classes correspondingly harder to exhaust. Second, keep the unattributed population above a floor: holding | S | ≥ s ∗ requires q ( N − K ) ≥ s ∗ − 1 , so an operator must either bound K or grow N to compensate. For a deployment targeting s ∗ = 128 —the point at which a re-identification guess does no better than 2 − 7 —under a bucketing that leaves q = 0.1 , that is 1270 unattributed records, and it must hold at every moment rather than on average. Since enrolment is the only lever that raises N while claims retire records from exhaustible classes, records must be issued at least as fast as classes are drained: with issuance rate λ and claim rate μ , the population available to hide in follows U ( t ) = U 0 + ( λ − μ ) t , and  λ ≥ μ is necessary for any permanent floor. A pilot with a few hundred enrolled patients does not reach 1270 at any tree depth, which is the concrete form of the warning that Section 3.2 states qualitatively.
We are explicit about what (9) is. It is an expectation under a stated arrival model, computed from the definition of S and from the attribution channels the threat model already admits; it is not a measurement, and our evaluation—a 16-leaf synthetic registry (Section 4.1)—cannot observe anonymity-set behaviour at any scale, which Section 4.10 records as a limitation. Its value is that it converts that limitation into a requirement an operator can check against their own enrolment, corruption and claim figures before deploying rather than after.

3.7.6. Proof Front-Running

A submitted claim transaction is public in the mempool before inclusion. Were the proof not bound to the submitting account, an observer could copy ( x , π ) and submit it first: the statement would be unchanged, so the copy verifies, the nullifier is consumed, and the legitimate patient’s transaction reverts—a griefing attack, and an outright theft if the contract disburses to msg.sender. We record this explicitly because the attack is easy to overlook: it defeats no cryptographic property, and a system can satisfy Propositions 1 and 2 and still be unusable because of it.
The recipient binding of (5) closes it. Since rcpt is part of the statement x and the contract rejects any claim with rcpt ≠ msg . sender , a copied proof is valid only for the account named in it. An adversary who resubmits the proof pays gas to send the patient’s payout to the patient. Proof malleability does not help: a re-randomized proof attests to the same statement, hence to the same rcpt .
Proposition 3
(Front-running resistance). Under the assumptions of Proposition 1, no adversary A who observes a pending claim ( x , π ) can cause the associated payout to be sent to an address other than the rcpt named in x, except by extracting a witness for a statement with a different rcpt , which contradicts knowledge soundness.
The cost is one additional R1CS constraint and one additional public input, measured in Section 4.6 at + 6967  gas for verifyProof and + 6983  gas for submitClaim—an increase of 1.9%.

3.8. Worked Example: Diabetes-Care Reimbursement

We instantiate the framework with a diabetes-care reimbursement scenario that is also the exact test vector shipped with the artifact (Figure 3). In that figure, the red panel lists the values that never leave the patient’s device at claim time and the green panel the only information revealed on-chain; the issuing hospital, however, already holds every red value, having created the record; what blinded issuance denies it is the ability to recognize the resulting claim on-chain.
Figure 3. Worked scenario: diabetes-care reimbursement.
A hospital issues patient P a record with diagnosis code c = 250 (ICD-9, diabetes mellitus), laboratory value v = 7.0 (HbA1c, %), policy pid = 42 , and coverage ceiling cc = 5000 monetary units. The insurer’s public policy covers diagnosis set C = { 100 , 175 , 250 , 300 , 401 , 402 , 500 , 999 } and the HbA1c band [ ℓ min , ℓ max ] = [ 5 , 10 ] . The record occupies leaf idx = 3 of the registry, and the patient submits a claim of a = 1500 units. Note that HbA1c is carried as an integer percentage here; a deployment needing decimal precision would scale the value by a fixed factor before committing it, since the 64-bit comparators of Section 3.4 operate on integers.
When and where information is revealed. At issuance (Phase II), the chain learns only the updated root R; no record field appears on-chain. At claim time (Phase III), the contract—and hence the insurer and any chain observer—learns only that some authority-signed record in the registry satisfies (2)–(4) for the public claim amount a = 1500 , together with the opaque nullifier nf . The diagnosis code, the HbA1c value, the ceiling, and the policy identifier never leave the patient’s device. A second submission for the same record reproduces nf = Poseidon ( s , idx ) and is rejected by the nullifier check, which we also verify functionally in Section 4.5.
Two qualifications apply to this scenario and should be read alongside it. First, the hospital necessarily knows the clinical fields—it created them—and it knows idx ; what it does not know, under the blinded issuance of Section 3.1, is s, and without s it cannot compute nf or recognize the claim on-chain. Had issuance not been blinded, the issuer would see every claim its records generate, which is why we treat that design point as unacceptable rather than as a limitation. Second, with only the eight covered codes and the single band [ 5 , 10 ] of this policy, the anonymity set S of Proposition 2 comprises those registry leaves whose ceiling admits a = 1500 —a set that is large only if many patients hold comparable policies. The scenario is presented to make the disclosure boundary concrete, not as evidence of a particular anonymity level.

4. Experimental Results

4.1. Implementation and Experimental Setup

4.1.1. Which Circuit the Numbers Describe

We state this first because it qualifies everything that follows. The relation R of Definition 1 is the canonical hardened circuit: blinded issuance, per-level booleanity, the  idx -bound nullifier of (8), and recipient binding. Compiled with circom 2.2.3 under –O2 it yields 10,050 constraints at depth 20, and the predicate ablation on that circuit gives 9842/9970/10,034/10,050—so the eligibility logic accounts for 208 constraints, or 2.1%, the same share reported below. Each Merkle level costs 243 constraints, of which one is the booleanity check.
The primary campaign of Section 4.3, Section 4.4, Section 4.5, Section 4.6, Section 4.7 and Section 4.8 predates two of these four features. Its circuit omitted blinded issuance and recipient binding, and—as we discovered when reconciling the campaigns—it also omitted the explicit per-level booleanity constraint: compiling the current circuit with that single line removed reproduces the primary campaign’s counts exactly (8848/9816/10,784 at depths 16/20/24). Since MultiMux1 interpolates rather than constrains its selector, nothing else enforced b i ∈ { 0 , 1 } in that circuit, and the argument of Section 3.4 for why the constraint is not optional applies to it. The primary numbers therefore describe a circuit that does not satisfy R , and we report them as a measurement history rather than as a specification of the deployed system.
Two of the three quantities have since been re-measured on the canonical circuit, and we state plainly which. Constraint counts are canonical throughout: the figures above, and the Δ column of Table 4, come from compiling the circuit of Definition 1 directly. Gas is canonical: the two 16-public-input rows reported in Section 4.5 are measured on the canonical signal layout rather than extrapolated from the primary rows, and because Groth16 verification cost is a function of the public-signal count and calldata rather than of circuit size—a property we confirm experimentally there—those figures are exact for the canonical circuit. Wall-clock times in Table 5 remain those of the primary campaign. Proving time depends on constraint count, so the canonical circuit, being 234 constraints larger at depth 20, will prove marginally more slowly; the difference is a 2.4% increase in circuit size and we do not expect it to change any conclusion drawn here, but we label the column as primary-campaign rather than restate it. The artifact ships a single script that regenerates Table 5 against the canonical circuit on any machine with the toolchain installed. We prefer to expose this discrepancy, and to be precise about which columns it still touches, rather than quietly restate old figures against a new relation.
Table 4. Circuit complexity by predicate configuration at Merkle depth 20.
Table 5. Groth16 performance by Merkle depth.
Leaving a column labelled but unbounded would be a weaker disclosure than the one available, so we bound it. Proving time is empirically sub-linear in constraint count across the range we measured: depths 16 to 24 span 8848 → 10,784 constraints, an increase of 21.9%, for  2.07 → 2.32  s, an increase of 12.1%—an elasticity of 0.55. The canonical circuit at depth 20 is 10,050 constraints against 9816, an increase of 2.4%, which at that elasticity predicts 2.25 →  ≈2.28 s, about 1.3%. That is well inside the 11% relative standard deviation of the timing measurement itself, so the substitution the reader is being asked to make is smaller than the noise band already reported. To make the mismatch visible at the point of use rather than only here, Table 5 now carries the canonical constraint count for each depth alongside the primary-campaign timings, and its note gives the primary counts those timings describe.

4.1.2. Two Measurement Campaigns

The results below come from two independent runs, and we keep them separate throughout. Section 4.3, Section 4.4, Section 4.5, Section 4.6, Section 4.7 and Section 4.8 report the primary campaign: the base circuit (15 public inputs, no recipient binding) on the machine described below. Section 4.6 reports a secondary campaign on different hardware, which re-derives the circuit from the specification in Section 3 and measures the incremental cost of the hardening. Wall-clock times from the second campaign are not comparable to the first and are not reported; constraint counts and gas are deterministic functions of the circuit and the bytecode, so those transfer.
The circuit is implemented in circom 2.1.9 [12] and proven with snarkjs 0.7.6 [13], using Poseidon [39] over the BN254 scalar field and EdDSA over Baby Jubjub [42]. Groth16 is the primary proving system [6]. The verifier and registry contracts are compiled with Solidity 0.8.36 (optimizer on, 200 runs) and executed on an in-process Ethereum-compatible node to obtain deterministic gas measurements.
Because every gas figure in this paper is hardfork-dependent, we state the execution environment precisely. Contracts are compiled with –evm-version shanghai and executed under the Shanghai rule set; the elliptic-curve precompiles ecAdd, ecMul, and ecPairing carry their post-EIP-1108 prices of 150, 6000, and  45,000 + 34,000 k gas for k pairs, respectively, which have not changed in subsequent upgrades. We have verified that the Prague/Pectra calldata repricing of EIP-7623 [47] does not affect the reported figures: the claim transaction carries 736 bytes of calldata, giving a floor of 21,000 + 10 × 4 × 736 = 50,440  gas, an order of magnitude below the 313,010 gas actually consumed, so the floor never binds. The measurements were taken with Ganache 7.9.2, which reached end of life in September 2023 and supports Shanghai as its most recent hardfork. Since the gas cost of this workload is dominated by the curve precompiles and by intrinsic and calldata charges, none of which changed between Shanghai and the current rule set, we expect the values to carry over unchanged, though we have not re-measured them under a later hardfork. A reproducer can confirm this by substituting a current local EVM—Foundry’s anvil (https://getfoundry.sh, accessed on 4 September 2026), for example—for Ganache, which the measurement scripts support without modification.
All measurements were taken on a single x86-64 Linux (Ubuntu 24.04) machine with one vCPU of an Intel Xeon processor (Intel Corporation, Santa Clara, CA, USA) at 2.80 GHz and 4 GB RAM, using Node.js v22.22.2. The snarkjs prover runs single-threaded WebAssembly; absolute times are therefore conservative, and native multi-threaded provers (e.g., rapidsnark, https://github.com/iden3/rapidsnark, accessed on 4 September 2026) would be substantially faster. Each configuration begins with one discarded warm-up iteration so that WebAssembly module compilation and first-touch allocation are excluded; reported values are then means over 3 witness-generation runs and 5 proving/verification runs, matching the benchmark invocations documented in the artifact. We report means with the observed relative standard deviation rather than confidence intervals, because at these sample sizes an interval would convey false precision; a referee wishing to see tighter bounds can raise the run counts in the benchmark script. Witness-generation and proving times are stable (relative standard deviation at most 11%). Verification is a sub-40 ms quantity for which occasional runtime pauses dominate: its relative dispersion reaches 36%, corresponding to an absolute spread of only about 11 ms, so verification figures should be read as “≈30 ms” rather than as precise inter-configuration differences. Peak resident set size is a process high-water mark and likewise varies with garbage-collection timing rather than with circuit size at this scale; the same caveat applies to the setup column of Table 5, whose non-monotonicity across depths (23.8, 31.0, 28.5 s) reflects its single-run character and not a property of the circuits, which grow monotonically. Gas values are deterministic. Synthetic records (16 leaves, target index 3) instantiate the scenario of Section 3.8; the benchmark proving keys are generated directly from the ceremony output without additional contributions, which is adequate for performance measurement, whereas a production deployment requires a multi-party phase-2 ceremony.

4.2. Reproducibility

The complete pipeline is scripted in the artifact and reduces to the following steps (shown for depth 20; $S denotes the snarkjs CLI). The circuits, smart contracts, input generator, and benchmarking scripts, together with the full reproduction guide—exact package versions, the compilation of every circuit configuration, the powers-of-tau and Groth16 setup, the benchmark invocations behind Table 4 and Table 5, the gas harness behind Table 6, and the PLONK note—are available at https://github.com/wwarodom/zk_code (accessed on 29 July 2026).
Table 6. Measured on-chain cost (gas).
  • circom d20_full.circom –r1cs –wasm -l node_modules -o build
  • $S powersoftau new bn128 14 pot0.ptau → contribute → prepare phase2
  • $S groth16 setup d20_full.r1cs pot14_final.ptau circuit.zkey
  • node build_input.js 20 (synthetic records, Merkle path, EdDSA signature; the signature is re-verified in JavaScript before proving)
  • $S groth16 fullprove input.json circuit.wasm circuit.zkey
  • $S zkey export solidityverifier → deploy verifier + registry on Ganache → measure gas via transaction receipts and estimateGas
Four circuit configurations isolate predicate costs (Table 4); three Merkle depths d ∈ { 16 , 20 , 24 } measure registry scalability (Table 5); the on-chain protocol is measured end-to-end including the double-claim rejection path (Table 6).

4.3. Circuit Complexity

Table 4 reports the compiled R1CS size as predicates are added incrementally at depth 20. The signature-plus-membership baseline dominates at 9608 constraints (97.9% of the full circuit): EdDSA verification and the 20 Poseidon levels of the Merkle path are the expensive components. The three eligibility predicates together add only 208 constraints (2.1%)—128 for the two 64-bit range comparators, 64 for the ceiling comparator, and 16 for the eight-element set-membership gadget. Privacy for the domain logic is therefore nearly free once the authentication core is paid for; richer policies (more codes, more bounds) would scale at tens of constraints per predicate. Witness generation stays around 0.1 s (≤106 ms) in every configuration—these are means of three runs, and the differences between the four configurations fall within measurement noise—and the proving-key size grows only marginally with the predicates ( 6.2 → 6.3  MB).
The public-input vector is held fixed at 15 signals across all four rows of Table 4: the policy parameters are declared public even in the reduced configurations, where no constraint consumes them. This keeps the Δ column a clean measure of predicate cost and, because verification gas is driven by the public-input count rather than by circuit size (Section 4.5), keeps the four configurations comparable on-chain as well.

4.4. Proving Performance and Scalability

Table 5 reports end-to-end cost as the registry capacity grows from 2 16 to 2 24 records, and Figure 4 plots the prover time. All entries are means except the setup column: setup is a one-time offline operation and was measured once per circuit, so that column is single-run rather than averaged, which is why it is not monotone in depth. Proof size is protocol-constant and is listed for completeness rather than as a measurement. Each additional Merkle level adds exactly 242 constraints (one Poseidon permutation plus selector logic), so circuit size—and, empirically, prover time—grows monotonically with d (2.07 s → 2.25 s → 2.32 s) while the proof size stays constant at 256 bytes (8 field elements). Verification cost is constant in the circuit size, since a Groth16 verifier performs a fixed pairing check regardless of how many constraints the proof attests to; it is, however, linear in the number of public inputs, which is held at 15 across all three depths here. The measured values cluster at ≈32 ms and their apparent variation across depths is measurement noise (Section 4.1). Increasing the registry capacity by a factor of 256 (depth 16 → 24) increases proving time by only 12%, confirming that registry scale is not a practical barrier. Peak prover memory stays in the 174–202 MB band across all depths, comfortably within commodity hardware. Figure 4 plots the three measured prover times against depth: the growth is linear in circuit size, at 242 constraints per level, while proof size and verification cost remain flat. Three points establish a trend but not a slope with confidence, so the figure should be read as corroborating the constraint-count argument rather than as an independent fit.
Figure 4. Prover time versus Merkle depth.
For a universal-setup alternative, converting the full circuit to PLONK constraints yields 79,499 gates—an 8.1 × expansion over R1CS—which requires a 2 17 powers-of-tau ceremony; the corresponding proof comprises 24 field elements (768 B) in the snarkjs Solidity verifier interface, three times the Groth16 proof. Completing the 2 17 ceremony and PLONK proving exceeded the single-vCPU budget of our measurement environment, so Table 5 reports measured values for Groth16 only; the artifact includes the scripts to reproduce the PLONK column on stronger hardware. The qualitative trade-off is well understood: PLONK removes the per-circuit ceremony at the price of larger proofs, higher prover cost, and higher verification gas [14,20].

4.5. On-Chain Cost

Table 6 reports gas on an Ethereum-compatible network. Two measurement conventions apply to it. Deployments and state-changing calls are transaction-receipt values, i.e. gas actually consumed; verifyProof, being a view function, is instead measured with estimateGas on the call, which includes the 21,000-gas intrinsic charge and the calldata cost that an external invocation would pay. The two rows are therefore directly comparable, which is what makes the difference between them meaningful. Verifier and registry deployments are one-time costs. The direct verifyProof call costs 313,010 gas (dominated by the pairing precompiles plus calldata for the 15 public inputs). This decomposes as 21,000  gas intrinsic, 45,000 + 4 × 34,000 = 181,000  gas for the four-pair ecPairing, 15 × ( 6000 + 150 ) = 92,250  gas for the scalar multiplications and additions that fold the public inputs into the verification equation, and  736 × 16 = 11,776  gas of calldata, totalling 306,026  gas of modelled cost against 313,010  gas measured—the ≈2% residual being dispatch, memory expansion, and argument decoding. We give the decomposition because it makes the scaling behaviour explicit: each additional public input costs approximately 6150 gas of precompile work plus 512 gas of calldata, about 6700 gas in total. Policy complexity is therefore not free on-chain. The eight covered diagnosis codes of our policy account for roughly 53,000  gas, and a policy with 64 covered codes would add a further ≈375,000 gas, more than doubling the transaction. Deployments with large code sets should commit the covered set to a single hashed public input and prove membership against that commitment in-circuit, moving the cost from the verifier into the prover, where Table 4 shows it is inexpensive. The full submitClaim transaction costs 367,748 gas and additionally performs the binding checks against the registered root, authority key, and policy parameters, and one cold SSTORE that records the nullifier; the 54,738-gas difference over the bare verification is the total price of policy binding and double-claim protection. That difference should be read as close but not exact: both figures carry the same 21,000-gas intrinsic charge, which cancels, and both carry calldata of the same 736 bytes, which very nearly cancels—the two calls differ only in selector and argument encoding, a handful of gas. Subtracting an estimateGas figure from a receipt is therefore clean to within tens of gas, not exactly zero, and the 54,738 should not be over-read as an exact decomposition. A second submission carrying the same nullifier was rejected, confirming double-claim protection functionally. Because Groth16 proofs are malleable (Section 3.7), the guarantee rests on the nullifier and not on proof-byte equality: the contract stores N and never compares proofs, so a re-randomized proof for the same record is rejected on the same path. At this cost, claim verification is practical on low-fee EVM networks and rollups, while remaining a real design consideration for Ethereum mainnet deployment. Note that the measured submitClaim does not yet bind the recipient address; adding the front-running countermeasure of Section 3.7.6 raises the figure by approximately 6700 gas to ≈374,400 gas.

4.6. Cost of the Hardened Configuration

The blinded issuance of Section 3.1 and the recipient binding of (5) were specified after the primary campaign. To measure rather than estimate their cost, the circuit was re-derived from the specification and recompiled with circom 2.2.3 and circomlib 2.0.5 under –O2, and the on-chain path was rebuilt with an independently written registry contract (solc 0.8.36, optimizer 200 runs, –evm-version shanghai).

4.6.1. Calibration

A reconstruction is only useful if it reproduces the system it claims to re-derive, so we state the agreement before the new numbers. Across all six configurations of Table 4 and Table 5 the re-derived circuit exceeded the primary campaign by exactly d constraints—20 at depth 20, 16 at depth 16, 24 at depth 24. That residual is not noise, and it is not a reconstruction artefact: it is the booleanity constraint b i ( 1 − b i ) = 0 that (7) imposes at each of the d levels, and it is absent from the primary circuit. We confirmed this directly by deleting the constraint from the current circuit and recompiling, which reproduces the primary counts to the constraint at all three depths. The residual therefore measures a real omission rather than a difference of compiler version, and the primary circuit admits the non-Boolean-selector attack that Section 3.4 describes. This is the sharpest reason to treat the canonical circuit, not the primary one, as the object of the security claims. On the on-chain side the reconstruction reproduced Table 6 to within 0.01% for verifyProof ( 313,034 against 313,010 ) and 0.05% for submitClaim ( 367,946 against 367,748 ), the residual being the independently written registry. This agreement is what licenses transferring the increments below onto the primary measurements.

4.6.2. Measured Increments

Blinded issuance costs 213 constraints, and the recipient binding a further 1 constraint, so the hardened circuit at depth 20 compiles to 10,050 constraints against 9816 for the configuration of Table 4—a 2.4% increase, of which the booleanity fix is 20. On-chain, moving from 15 to 16 public inputs costs 6967 gas on verifyProof and 6983 gas on submitClaim; the hardened claim therefore costs ≈ 374,700  gas, 1.9% above the unhardened one. Both figures are deterministic and were identical across repeated runs. We note that the earlier analytical estimate for this increment, 6662 gas from the precompile-and-calldata model alone, was low by about 4.6%: the model omits the memory expansion and argument-decoding cost of the extra word, which is a useful caution against substituting such models for measurement.

4.6.3. Functional Checks

On the hardened contract, a claim submitted by the account named in the proof is accepted; the same proof submitted by a different account reverts with recipient mismatch, confirming Proposition 3; and a resubmission after success reverts with nullifier used, confirming case (c), the double-claim case, in the proof of Proposition 1. On the domain-separated contract of Section 3.5.2 a fourth check applies: the same proof submitted to a sibling registry sharing the verifier, policy and root but deployed at a different address reverts with domain mismatch. All four are asserted rather than printed, so the harness fails rather than reporting an unexpected reason, and each negative test runs before the successful claim—once the nullifier is consumed, nullifier used fires first and masks the reason under test.

4.7. Evidence Against Under-Constraining

Under-constrained circom circuits are the dominant vulnerability class in deployed zero-knowledge systems [48], and a paper that reduces its security to a relation R owes the reader an account of why its R1CS encoding is that relation and not a weaker one. We give the account in the only form we can defend: what was checked, what each check does and does not rule out, and what remains unchecked.
The hand-written surface is small, and we enumerate it. Every cryptographic component—Poseidon, EdDSAPoseidonVerifier, LessEqThan, IsEqual, MultiMux1—is instantiated unmodified from circomlib [12], so the constraints we author ourselves number four: the per-level booleanity constraint b i ( 1 − b i ) = 0 ; the linear recovery idx = ∑ i b i 2 i ; the set-membership accumulator ∑ i IsEqual ( c , C i ) ≡ 1 ; and the quadratic pin rcpt 2 = rcpt sq of (5). Every signal appearing in R is either an input to a circomlib template that constrains its own output, or occurs in one of these four. That qualification is load-bearing and we do not gloss it: MultiMux1 is precisely a template that does not constrain one of its inputs, which is why the first of our four constraints exists at all, and auditing this circuit is in part a matter of establishing which library templates share that property. The enumeration is therefore not a proof of well-constrainedness. It is a bound on what such a proof would have to cover, and it is what makes the audit below tractable at all.
Differential constraint counting found a real bug. Our strongest evidence is negative and was not sought. Re-deriving the circuit from Section 3 and comparing constraint counts against the primary campaign left a residual of exactly d constraints at every depth (Section 4.6), which we traced to a missing booleanity check. That is an under-constraining bug of precisely the class in question— MultiMux1 interpolates its selector rather than constraining it, so a malicious prover could choose b i ∉ { 0 , 1 } and reach an arbitrary root—and it was found by ablation over constraint counts, not by inspection and not by a tool. We record the method because it generalizes: for a circuit assembled from a documented library, the compiled constraint count is a checkable prediction, and a discrepancy against an independent re-derivation localizes to the component in which it arises. It is also a reason for candour about coverage: a technique that found one such bug in this circuit is not evidence that it was the only one.
Negative test vectors exercise the protocol-level rejections. The artifact’s scripts/reasons.js submits one valid proof from three positions and records the contract’s revert reason: the legitimate recipient is accepted; a second account submitting the identical proof reverts with recipient mismatch; and a resubmission after success reverts with nullifier used. The EdDSA signature is additionally re-verified in JavaScript before proving (Section 4.2), which catches a witness that satisfies the circuit’s signature constraints without being a valid signature. These are functional tests of the on-chain protocol. They do not test in-circuit constraint sufficiency, and we do not present them as though they did.
One invariant the enumeration surfaced. The membership accumulator constrains the sum of equality flags to be exactly one, not at least one. A covered set C containing a duplicated code therefore renders an otherwise valid record unprovable: the matching flag fires twice and the accumulator is unsatisfiable. This is a liveness rather than a soundness failure, and it is silent—the patient simply cannot generate a proof—so we state it as a registration invariant alongside the 2 64 bound of Section 3.4: the contract must reject any policy whose code set contains repeats. We note it here because enumerating the hand-written constraints is what exposed it.
What is not ruled out. We have not run an automated under-constrainedness analysis on this circuit, and we do not claim it is free of the class. Three tools would be needed for a defensible claim, and we name them because “formal verification is future work” is not an audit plan. Circomspect [49] is a static analyzer and linter that flags unconstrained signals, unused outputs, and precisely the MultiMux1-style idioms that admitted the bug above. Picus [50] decides under-constrainedness for a substantial fragment of circom by SMT-based uniqueness reasoning, which is the property R actually requires. ZKAP [48] applies anti-pattern detectors tuned to the vulnerability distribution observed across deployed circuits. Running all three against Definition 1 and reconciling their output against the four-constraint enumeration above is the concrete next step we commit to, and it is a prerequisite for any deployment carrying real claims rather than for the measurements reported here.

4.8. Comparison with Baselines

Table 7 contrasts the zero-knowledge approach with non-private baselines. Plaintext on-chain records make eligibility trivially verifiable but expose all clinical data permanently and irrevocably—a property that is difficult to reconcile with the erasure and rectification rights of GDPR Article 17 or PDPA Section 33. Encrypted off-chain storage with on-chain access control [7,8] protects data at rest but requires revealing record contents to whichever party evaluates eligibility, and offers no public verifiability of the decision. The proposed approach is the only one of the three that provides both public verifiability and non-disclosure, at the measured cost of 2.25 s of client-side proving and 367,748 gas per claim.
Table 7. Comparison against non-private baselines.
Only the zero-knowledge row of Table 7 is measured (Table 6). The two baseline rows are analytical estimates derived from EVM opcode pricing under the same Shanghai rule set used throughout Section 4.1—cold SSTORE  = 22,100 , cold SLOAD  = 2100 , intrinsic = 21,000 , non-zero calldata = 16 per byte. We give them analytically rather than by implementation for two reasons. The comparison turns on storage-access pricing, which is fixed by the protocol and not by how a baseline contract happens to be written; and a figure derived from four published constants and a stated layout is auditable in a way that a figure produced by our own unpublished baseline contract would not be, since a reader disputing any number below can recompute it without trusting our code. What such an estimate must get right is the layout, and the layout is where the previous version of this table was wrong.
The baseline layout is packed storage, and we state it. No competent implementation writes a record’s fields to one storage slot each; it declares them as a packed struct, and the EVM charges per 32-byte slot touched rather than per field. Our earlier estimate priced five separate cold SSTOREs and was wrong to do so. Taking realistic widths—diagnosis code 16 bits, laboratory value 16, policy identifier 32, coverage ceiling 64—the four fields a claim must be checked against occupy 128 bits and fit in a single slot; the record identifier is the key of the mapping that holds them and is not itself stored. A packed issuance is therefore one cold SSTORE at 22,100  gas plus 21,000 intrinsic, 160 × 16 = 2560 of calldata and a few hundred gas of shift-and-or packing: ≈46,000 gas, against the ≈134,000 that five separate slots would cost. A packed claim reads the slot back for 2100, plus intrinsic, 32 bytes of calldata and the three comparisons: ≈24,000 gas against ≈31,500 unpacked. The estimate is sensitive to one layout choice and we give the sensitivity rather than hide it: a design that also stores a 160-bit patient address as a struct field, instead of using it as the mapping key, pushes the record to 288 bits and two slots, giving ≈68,000 and ≈26,000 gas. We report the single-slot figures, which are the cheapest defensible reading of the baseline and therefore the least favourable to us. The encrypted-off-chain baseline stores a single 32-byte content identifier, is already minimal, and is unchanged.
One asymmetry remains, and we flag it rather than silently correcting it. The zero-knowledge row prices double-claim protection—the cold SSTORE that consumes the nullifier is inside the 367,748  gas of Section 4.5—whereas neither baseline row prices an equivalent. Adding one would cost the packed plaintext claim about 2900 gas, a warm SSTORE into the slot the claim has already read, and the encrypted-pointer claim about 22,100 , a fresh cold slot. We leave both baseline rows without it so that they remain a pure lower bound on what the non-private approaches cost; a reader who prefers the symmetric comparison can add these two figures and will find the multiples below fall, not rise.
The cost columns deserve comment, and the correction above changes what they say. The issuance columns are not directly comparable and we no longer present them as though they were: a plaintext issuance is a per-record cost, whereas the 47,178  gas of a zero-knowledge root update is a per-batch cost that covers every leaf inserted since the previous update. Written per record, zero-knowledge issuance is 47,178 / B for a batch of B leaves. At  B = 1 the two are at parity— 47,178 against ≈46,000—and the earlier claim that privacy is cheaper at issuance does not survive the packing correction in that regime. At  B = 10 it is already an order of magnitude cheaper, and the advantage grows linearly with batch size. The honest statement is therefore conditional on batching, and a deployment that inserts records one at a time gains nothing at issuance.
What the plaintext baseline buys is a cheap claim, and packing makes it cheaper still: ≈24,000 gas rather than ≈31,500. Privacy does not make the system uniformly more expensive, then; it shifts cost from issuance to verification, and the shift is large and roughly equal against either baseline— 15.3 × per claim against the packed plaintext baseline and 15.9 × against the encrypted-pointer baseline. Both multiples are larger than the 11.7 × we previously reported, and the increase is a consequence of correcting our own estimate rather than of any change to the measured zero-knowledge figure. At mainnet prices this is the dominant deployment consideration; on a rollup, where calldata and execution are one to two orders of magnitude cheaper, it is not.
One empirical calibration is available for the storage term of these estimates, and we report it because that term is the one a reader is most entitled to doubt. Our own registry performs a cold SLOAD per covered diagnosis code in its policy-equality loop, so measuring submitClaim against verifyProof across policy sizes isolates the loop directly; the artifact’s policy-size sweep (scripts/ncodes_bench.js) puts it at ≈2300 gas per iteration, against the 2100 the model assigns to a bare cold SLOAD. The model is therefore low by roughly 10% on the storage-read term, which would move a packed plaintext claim from ≈24,000 to ≈24,200 gas—inside the rounding already applied, and in the direction that makes our own comparison marginally more favourable. We report the check rather than apply the correction, and note that this is the sense in which the baseline rows are calibrated rather than merely asserted: the model’s dominant constant has been checked against a measurement on the same EVM configuration.

4.9. Projected Cost of a Migration to BLS12-381

BN254 offers roughly 100 bits of security after the Kim–Barbulescu improvements to the tower number field sieve [43], below the 128-bit level usually targeted for new deployments; BLS12-381 offers roughly 126. Since EIP-2537 [51] added BLS12-381 curve precompiles to Ethereum in the Pectra upgrade of May 2025, the migration can be priced from a published gas schedule rather than left as an open question, and we do so here. The figures are a model and not a measurement—we have not built a BLS12-381 verifier—but every term is a published constant applied to the verifier structure that Section 4.5 already decomposes, so a reader can recompute all of them.
Three terms change, and they do not move in the same direction. The pairing gets cheaper. EIP-2537 prices BLS12_PAIRING_CHECK at 37,700 + 32,600 k gas for k pairs, so the fixed four-pair Groth16 check costs 37,700 + 4 × 32,600 = 168,100  gas, against the 45,000 + 4 × 34,000 = 181,000 of the post-EIP-1108 BN254 precompile—a saving of 12,900  gas. The public-input folding gets more expensive. On BN254 the 16 public inputs are folded with 16 ecMul and 16 ecAdd operations, 16 × ( 6000 + 150 ) = 98,400  gas. EIP-2537 replaces these with a single multi-scalar multiplication priced at ⌊ k · 12,000 · discount ( k ) / 1000 ⌋ ; with discount ( 16 ) = 677 that is ⌊ 16 · 12,000 · 677 / 1000 ⌋ = 129,984  gas, plus one BLS12_G1ADD at 375 for the constant term, giving 130,359  gas, or  31,959 more than BN254. The proof gets larger. A BLS12-381 field element is 48 bytes and the precompile ABI pads each to 64, so the proof travels as 128 + 256 + 128 = 512  bytes against 256 on BN254, adding 256 × 16 = 4096  gas of calldata.
The net is − 12,900 + 31,959 + 4096 = + 23,155  gas. The canonical claim therefore moves from the measured 374,929  gas of Table 6 to ≈398,100, an increase of 6.2%, and a bare verifyProof from 320,001 to ≈343,200, an increase of 7.2%. The marginal price of a public input rises with it: the 16-to-17 step of the multi-scalar multiplication costs ⌊ 17 · 12,000 · 673 / 1000 ⌋ − 129,984 = 7308  gas plus 512 of calldata, so ≈7800 against the ≈6700 of Section 4.5—which strengthens rather than weakens this paper’s recommendation to commit large policies rather than enumerate them.
Two conclusions follow, and the first is not the one we expected. The migration is dominated by the public-input folding, not by the pairing. The pairing—the operation that an intuition about “a bigger curve costs more” would blame—becomes 7.1% cheaper, and the entire penalty arises from scalar multiplication and calldata, both of which scale with the statement rather than with the curve. This is the same asymmetry the rest of Section 4 reports, appearing again in a place we had not looked. Second, at roughly 26 additional bits of security for roughly 6% additional gas per claim, the trade is economically unremarkable, and the case against BN254 is not a cost objection. What the migration does cost outright is the constant 256-byte proof this paper advertises, which becomes 384 bytes of proof data—512 in the padded encoding the precompiles consume—together with a fresh per-circuit ceremony over the new curve. Both circom and snarkjs accept BLS12-381 as a compilation and setup target [12,13], so circuit compilation, the ceremony and off-chain proving are a re-parameterization rather than a rewrite. On-chain verification is not, and that is the part this model prices: snarkjs emits only a BN254 Solidity verifier, with the alt-bn128 moduli and the 0x06/0x07/0x08 precompile addresses written into the template, so a BLS12-381 verifier must be authored against the EIP-2537 precompiles with 381-bit field elements carried across several machine words. The costing above assumes such a verifier performs the same four-pair check and folds the public inputs with a single multi-scalar multiplication; building and measuring it remains future work.

4.10. Discussion and Limitations

The evaluation supports three observations. First, the dominant circuit cost is authentication (signature and Merkle membership), not the eligibility logic: under the PDPA’s data-minimization lens, adding non-disclosure to the domain predicates costs only ∼2% of the circuit once authenticated provenance is required at all. Second, Groth16’s constant 256-byte proof and flat verification make on-chain cost independent of registry size—depth 16 and depth 24 verify at identical gas—but, as Section 4.5 shows, not of policy complexity, since each covered code declared as a public input costs ≈6700 gas. The scalability story is thus asymmetric: the registry scales for free, the policy does not, and a large policy should be committed rather than enumerated. Third, absolute prover times reported here are conservative: they were measured on a single vCPU with a WebAssembly prover, and both multi-threading and native provers reduce them substantially.
Limitations. We group the limitations by what a reader should conclude from them.
Split measurement campaigns. The hardening increments of Section 4.6 were measured on different hardware from the primary campaign. Constraint counts and gas are deterministic given the circuit and the bytecode, so this does not affect them; wall-clock proving time for the hardened circuit is correspondingly not reported, and a deployment wanting that figure must measure it. Groth16 supplies knowledge soundness but not simulation extractability, so the non-malleability the application needs is supplied by the nullifier and the recipient binding rather than by the argument system [18,19].
Assumptions carried into deployment. A production system requires a multi-party phase-2 ceremony [40]; our benchmarks used a non-ceremonial key, which affects trust but not performance. BN254 provides approximately 100 bits of security [43], below the level usually targeted for new deployments; Section 4.9 prices the BLS12-381 migration from the EIP-2537 gas schedule at roughly 6% of the claim transaction, so the objection to BN254 is one of diligence rather than of cost, but the migration has been modelled here and not measured. Correctness of the construction is argued in Section 3.7 but the circuit itself has not been formally verified, and under-constraining bugs in circom circuits are a well-documented and empirically common class [48]; Section 4.7 sets out what our checks do and do not establish, and names the analyses that a deployment carrying real claims would need to run first. The domain separator of Section 3.5.2 is implemented and measured, but as a variant alongside Definition 1 rather than inside it: the constraint counts and gas of Table 4, Table 5 and Table 6 describe the 16-signal relation, and a deployment should use the 17-signal configuration and add the measured increment.
Scope of the evaluation. Measurements come from a single machine with synthetic records and a 16-leaf registry; anonymity-set behaviour, which Proposition 2 identifies as the binding privacy constraint, cannot be observed at that scale and is not evaluated here. Section 3.7.5 models it instead, and the resulting enrolment condition is a design rule derived from the definition of S , not an empirical finding. The PLONK column was left unmeasured within this environment’s budget (Section 4.4). No user study or clinical deployment was conducted, so claims about practicality are claims about cost, not about acceptability to patients or insurers.

5. Conclusions

We presented a zero-knowledge framework for verifying health-insurance eligibility on-chain without disclosing sensitive clinical data. The system combines authority-signed records, an on-chain Merkle registry, composite eligibility predicates, and a nullifier that prevents double claims while preserving anonymity. A complete, reproducible prototype demonstrates practicality: the canonical circuit of Definition 1 compiles to 10,050 constraints, of which the eligibility predicates are 2.1%; proofs are a constant 256 bytes; verification is a fixed four-pair check whose cost is set by the public-input count; and a repeated claim is rejected. Claim soundness, claim unlinkability, and front-running resistance are reduced to the knowledge soundness and zero-knowledge of Groth16, the collision resistance and keyed unpredictability of Poseidon, and the unforgeability of EdDSA (Propositions 1–3). Constraint counts and gas are reported for that canonical circuit; the wall-clock times of Table 5 were measured on an earlier circuit lacking three of its four hardening features, as Section 4.1 states, and should be re-measured before they are relied upon.
Two findings generalize beyond this application. Privacy for the domain logic is close to free once authenticated provenance is required at all, so the design question is not whether to add predicates but how to authenticate; and on-chain cost scales with the number of public inputs rather than with circuit size, which makes the public-input vector, not the constraint count, the object to optimize in any on-chain zk deployment. The second finding survives a change of curve and indeed sharpens under one: the BLS12-381 costing of Section 4.9 shows the pairing growing cheaper while the public-input folding grows dearer, so the quantity to optimize is the same on either curve.
A third conclusion is a caution rather than a finding, and we place it beside them because it is the one a deployment is most likely to get wrong. The anonymity a claim enjoys is set by the number of registry records consistent with its public statement, and it is eroded not by use as such but by attribution— q ( a ) ( N − K ) + 1 records once K of them have been tied to claims, by (9)—so a deployment must bound the corrupted and observable fraction, and enrol fast enough to keep amount classes from being exhausted, if it is to hold any anonymity floor at all. Tree depth buys capacity, and capacity is not privacy.
Future work includes re-measuring wall-clock cost against the canonical circuit, completing the PLONK and transparent-system comparison on multi-core hardware, implementing and measuring the BLS12-381 migration whose gas penalty Section 4.9 projects at 6.2% of a claim, folding the domain separator of Section 3.5.2 into the canonical relation and re-measuring the tables against the 17-signal configuration, running the automated under-constrainedness analyses named in Section 4.7 and formally verifying the circuit against Definition 1, validating the anonymity-set model of (9) against a registry large enough to exhibit the effect, recursive proof composition to aggregate multiple claims, dynamic on-chain Merkle updates, post-quantum-secure proving systems, and extensions to multi-authority settings and richer policy logic.

Author Contributions

Conceptualization, W.W. (Warit Werapun) and W.W. (Warodom Werapun); methodology, W.W. (Warodom Werapun) and W.W. (Warit Werapun); software, W.W. (Warit Werapun) and W.W. (Warodom Werapun); validation, W.W. (Warit Werapun) and W.W. (Warodom Werapun); formal analysis, W.W. (Warodom Werapun) and W.W. (Warit Werapun); investigation, W.W. (Warit Werapun) and W.W. (Warodom Werapun); resources, W.W. (Warodom Werapun); data curation, W.W. (Warit Werapun); writing—original draft preparation, W.W. (Warit Werapun) and W.W. (Warodom Werapun); writing—review and editing, W.W. (Warodom Werapun) and W.W. (Warit Werapun); visualization, W.W. (Warit Werapun); supervision, W.W. (Warodom Werapun); project administration, W.W. (Warodom Werapun); funding acquisition, W.W. (Warodom Werapun). All authors have read and agreed to the published version of the manuscript.

Funding

This research received no external funding.

Institutional Review Board Statement

Not applicable. This study did not involve human participants, human material, human tissue, or human data. All records used in the evaluation are synthetic values generated by the accompanying artifact; the diabetes-care scenario of Section 3.8 is illustrative and does not describe any real patient.

Data Availability Statement

The data presented in this study are available on request from the corresponding author. All records used in the evaluation are synthetic values generated deterministically by the accompanying implementation, whose location is given in Section 4.2; no clinical, personal, or otherwise pre-existing data were created or analyzed in this study.

Conflicts of Interest

The authors declare no conflict of interest.

Abbreviations

The following abbreviations are used in this manuscript:
BCBlockchain
BN254Barreto–Naehrig curve of 254 bits
CRSCommon reference string
DRLDeep reinforcement learning
EdDSAEdwards-curve digital signature algorithm
EUF-CMAExistential unforgeability under chosen-message attack
EVMEthereum virtual machine
GDPRGeneral Data Protection Regulation
HIPAAHealth Insurance Portability and Accountability Act
MSMMulti-scalar multiplication
PDPAPersonal Data Protection Act
PLONKPermutations over Lagrange-bases for oecumenical non-interactive arguments of knowledge
R1CSRank-1 constraint system
RSSResident set size
SNARKSuccinct non-interactive argument of knowledge
STARKScalable transparent argument of knowledge
UAVUnmanned aerial vehicle
ZKPZero-knowledge proof

References

  1. European Parliament and Council of the European Union. Regulation (EU) 2016/679 of 27 April 2016 on the Protection of Natural Persons with Regard to the Processing of Personal Data and on the Free Movement of Such Data (General Data Protection Regulation); Official Journal of the European Union L 119; European Parliament and Council of the European Union: Brussels, Belgium, 2016; pp. 1–88.
  2. United States Congress. Health Insurance Portability and Accountability Act of 1996, Public Law 104-191; 110 Stat. 1936; United States Congress: Washington, DC, USA, 1996.
  3. Government of Thailand. Personal Data Protection Act, B.E. 2562 (2019); Royal Thai Government Gazette: Bangkok, Thailand, 2019; Volume 136, Part 69a, pp. 52–95.
  4. Hölbl, M.; Kompara, M.; Kamišalić, A.; Nemec Zlatolas, L. A Systematic Review of the Use of Blockchain in Healthcare. Symmetry 2018, 10, 470. [Google Scholar] [CrossRef] [Scilit]
  5. Goldwasser, S.; Micali, S.; Rackoff, C. The Knowledge Complexity of Interactive Proof Systems. SIAM J. Comput. 1989, 18, 186–208. [Google Scholar] [CrossRef] [Scilit]
  6. Groth, J. On the Size of Pairing-Based Non-Interactive Arguments. In Proceedings of the Advances in Cryptology—EUROCRYPT 2016; Springer: Berlin/Heidelberg, Germany, 2016; Volume 9666, pp. 305–326. [Google Scholar] [CrossRef] [Scilit] [PubMed]
  7. Azaria, A.; Ekblaw, A.; Vieira, T.; Lippman, A. MedRec: Using Blockchain for Medical Data Access and Permission Management. In Proceedings of the 2016 2nd International Conference on Open and Big Data (OBD), Vienna, Austria, 22–24 August 2016; pp. 25–30. [Google Scholar] [CrossRef] [Scilit]
  8. Dagher, G.G.; Mohler, J.; Milojkovic, M.; Marella, P.B. Ancile: Privacy-Preserving Framework for Access Control and Interoperability of Electronic Health Records Using Blockchain Technology. Sustain. Cities Soc. 2018, 39, 283–297. [Google Scholar] [CrossRef] [Scilit]
  9. Bai, T.; Hu, Y.; He, J.; Fan, H.; An, Z. Health-zkIDM: A Healthcare Identity System Based on Fabric Blockchain and Zero-Knowledge Proof. Sensors 2022, 22, 7716. [Google Scholar] [CrossRef] [Scilit] [PubMed]
  10. Sharma, B.; Halder, R.; Singh, J. Blockchain-Based Interoperable Healthcare Using Zero-Knowledge Proofs and Proxy Re-Encryption. In Proceedings of the 2020 International Conference on COMmunication Systems & NETworkS (COMSNETS), Bengaluru, India, 7–11 January 2020; pp. 1–6. [Google Scholar] [CrossRef] [Scilit]
  11. Merkle, R.C. A Digital Signature Based on a Conventional Encryption Function. In Proceedings of the Advances in Cryptology—CRYPTO’87; Springer: Berlin/Heidelberg, Germany, 1988; Volume 293, pp. 369–378. [Google Scholar] [CrossRef] [Scilit] [PubMed]
  12. Bellés-Muñoz, M.; Isabel, M.; Muñoz-Tapia, J.L.; Rubio, A.; Baylina, J. Circom: A Circuit Description Language for Building Zero-Knowledge Applications. IEEE Trans. Dependable Secur. Comput. 2023, 20, 4733–4751. [Google Scholar] [CrossRef] [Scilit]
  13. iden3. Snarkjs: JavaScript and WASM Implementation of zk-SNARK and PLONK Schemes, Version 0.7.6. Software, 2024; 0KIMS Association: Zug, Switzerland, 2024. [Google Scholar]
  14. Gabizon, A.; Williamson, Z.J.; Ciobotaru, O. PLONK: Permutations over Lagrange-Bases for Oecumenical Noninteractive Arguments of Knowledge; Cryptology ePrint Archive, Paper 2019/953; International Association for Cryptologic Research (IACR): Santa Clara, CA, USA, 2019. [Google Scholar]
  15. Bünz, B.; Bootle, J.; Boneh, D.; Poelstra, A.; Wuille, P.; Maxwell, G. Bulletproofs: Short Proofs for Confidential Transactions and More. In Proceedings of the 2018 IEEE Symposium on Security and Privacy (SP), San Francisco, CA, USA, 21–23 May 2018; pp. 315–334. [Google Scholar] [CrossRef] [Scilit]
  16. Ben-Sasson, E.; Bentov, I.; Horesh, Y.; Riabzev, M. Scalable, Transparent, and Post-Quantum Secure Computational Integrity; Cryptology ePrint Archive, Paper 2018/046; International Association for Cryptologic Research (IACR): Santa Clara, CA, USA, 2018. [Google Scholar]
  17. Tang, X.; Qiao, K.; Wu, Q.; Wang, L. MPC-in-the-Head Zero-Knowledge Proof for Rank Syndrome Decoding via Mixed-Field Secret Sharing. Cryptography 2026, 10, 35. [Google Scholar] [CrossRef] [Scilit]
  18. Groth, J.; Maller, M. Snarky Signatures: Minimal Signatures of Knowledge from Simulation-Extractable SNARKs. In Proceedings of the Advances in Cryptology—CRYPTO 2017; Springer: Cham, Switzerland, 2017; Volume 10402, pp. 581–612. [Google Scholar] [CrossRef] [Scilit]
  19. Baghery, K.; Pindado, Z.; Ràfols, C. Simulation Extractable Versions of Groth’s zk-SNARK Revisited. In Proceedings of the Cryptology and Network Security—CANS 2020; Springer: Cham, Switzerland, 2020; Volume 12579, pp. 453–461. [Google Scholar] [CrossRef] [Scilit]
  20. Sun, X.; Yu, F.R.; Zhang, P.; Sun, Z.; Xie, W.; Peng, X. A Survey on Zero-Knowledge Proof in Blockchain. IEEE Netw. 2021, 35, 198–205. [Google Scholar] [CrossRef] [Scilit]
  21. Ben-Sasson, E.; Chiesa, A.; Garman, C.; Green, M.; Miers, I.; Tromer, E.; Virza, M. Zerocash: Decentralized Anonymous Payments from Bitcoin. In Proceedings of the 2014 IEEE Symposium on Security and Privacy (SP), San Jose, CA, USA, 18–21 May 2014; pp. 459–474. [Google Scholar] [CrossRef] [Scilit]
  22. Privacy & Scaling Explorations. Semaphore: A Zero-Knowledge Protocol for Anonymous Signaling; Software and protocol specification, 2023; Privacy & Scaling Explorations: Zug, Switzerland, 2023. [Google Scholar]
  23. Camenisch, J.; Lysyanskaya, A. An Efficient System for Non-Transferable Anonymous Credentials with Optional Anonymity Revocation. In Proceedings of the Advances in Cryptology—EUROCRYPT 2001; Springer: Berlin/Heidelberg, Germany, 2001; Volume 2045, pp. 93–118. [Google Scholar] [CrossRef] [Scilit] [PubMed]
  24. Sporny, M.; Longley, D.; Chadwick, D. Verifiable Credentials Data Model v1.1; W3C Recommendation: Cambridge, MA, USA, 2022. [Google Scholar]
  25. Hashim, F.; Shuaib, K.; Sallabi, F. Connected Blockchain Federations for Sharing Electronic Health Records. Cryptography 2022, 6, 47. [Google Scholar] [CrossRef] [Scilit]
  26. Zhou, L.; Diro, A.; Saini, A.; Kaisar, S.; Hiep, P.C. Leveraging Zero Knowledge Proofs for Blockchain-Based Identity Sharing: A Survey of Advancements, Challenges and Opportunities. J. Inf. Secur. Appl. 2024, 80, 103678. [Google Scholar] [CrossRef] [Scilit]
  27. Su, Z.; Wang, Y.; Xu, Q.; Zhang, N. LVBS: Lightweight Vehicular Blockchain for Secure Data Sharing in Disaster Rescue. IEEE Trans. Dependable Secur. Comput. 2022, 19, 19–32. [Google Scholar] [CrossRef] [Scilit]
  28. Wang, Y.; Su, Z.; Xu, Q.; Li, R.; Luan, T.H.; Wang, P. A Secure and Intelligent Data Sharing Scheme for UAV-Assisted Disaster Rescue. IEEE/ACM Trans. Netw. 2023, 31, 2422–2438. [Google Scholar] [CrossRef] [Scilit]
  29. Zheng, H.; You, L.; Hu, G. A Novel Insurance Claim Blockchain Scheme Based on Zero-Knowledge Proof Technology. Comput. Commun. 2022, 195, 207–216. [Google Scholar] [CrossRef] [Scilit]
  30. Qiu, Z.; Xie, Z.; Jiang, X.; Ran, C.; Chen, K. Novel Blockchain and Zero-Knowledge Proof Technology-Driven Car Insurance. Electronics 2023, 12, 3869. [Google Scholar] [CrossRef] [Scilit]
  31. Sanober, A.; Anwar, S. Zero-Knowledge Proof Enabled Blockchain Smart Contracts for Efficient Health Insurance System. Concurr. Comput. Pract. Exp. 2026, 38, e70607. [Google Scholar] [CrossRef] [Scilit]
  32. Bakare, D.E.; Amoo, A.O.; Onifade, M.T. Enhancing Privacy and Security in Blockchain-Based Health Insurance Management System Using Zero-Knowledge Proof. Int. J. Comput. Appl. 2025, 187, 44–53. [Google Scholar] [CrossRef] [Scilit]
  33. Albalwy, F. Zero-Knowledge-Based Policy Enforcement for Privacy-Preserving Cross-Institutional Health Data Sharing on Blockchain. Systems 2026, 14, 385. [Google Scholar] [CrossRef] [Scilit]
  34. Myeong, G.E.; Ram, K.S. Blockchain Based Zero Knowledge Proof Protocol for Privacy Preserving Healthcare Data Sharing. J. Technol. Inform. Eng. 2025, 4, 171–189. [Google Scholar] [CrossRef] [Scilit]
  35. Krishappa, N.; Shivappa, G.G.; Zachariah, S.; Thanushree, T.; Pattan, K.I.; Paria, A.; Hiremath, S.; Vaithiyanathan, R. A Blockchain-Based Framework with Zero-Knowledge Proof Incorporated for Safeguarded Sharing of Genomic Data Through Health Record Systems. Blockchain Healthc. Today 2025, 8, 419. [Google Scholar] [CrossRef] [Scilit] [PubMed]
  36. Anusuya, R.; Karthika Renuka, D.; Ghanasiyaa, S.; Harshini, K.; Mounika, K.; Naveena, K.S. Privacy-Preserving Blockchain-Based EHR Using ZK-SNARKs. In Proceedings of the Computational Intelligence, Cyber Security and Computational Models (ICC3 2021); Springer: Cham, Switzerland, 2022; Volume 1631, pp. 109–123. [Google Scholar] [CrossRef] [Scilit]
  37. Luong, D.A.; Park, J.H. Privacy-Preserving Blockchain-Based Healthcare System for IoT Devices Using zk-SNARK. IEEE Access 2022, 10, 55739–55752. [Google Scholar] [CrossRef] [Scilit]
  38. Alahmari, S.; Alshardan, A.; Al-Wesabi, F.N.; Sorour, S.; Alghushairy, O.; Alsini, R.; Khadidos, A.O.; Al Duhayyim, M. A Decentralized and Privacy-Preserving Framework for Electronic Health Records Using Blockchain. Alex. Eng. J. 2025, 126, 196–203. [Google Scholar] [CrossRef] [Scilit]
  39. Grassi, L.; Khovratovich, D.; Rechberger, C.; Roy, A.; Schofnegger, M. Poseidon: A New Hash Function for Zero-Knowledge Proof Systems. In Proceedings of the 30th USENIX Security Symposium (USENIX Security 21), Berkeley, CA, USA, 11–13 August 2021; pp. 519–535. [Google Scholar]
  40. Bowe, S.; Gabizon, A.; Miers, I. Scalable Multi-Party Computation for zk-SNARK Parameters in the Random Beacon Model; Cryptology ePrint Archive, Paper 2017/1050; International Association for Cryptologic Research (IACR): Santa Clara, CA, USA, 2017. [Google Scholar]
  41. Bernstein, D.J.; Duif, N.; Lange, T.; Schwabe, P.; Yang, B.Y. High-Speed High-Security Signatures. J. Cryptogr. Eng. 2012, 2, 77–89. [Google Scholar] [CrossRef] [Scilit]
  42. WhiteHat, B.; Bellés, M.; Baylina, J. EIP-2494: Baby Jubjub Elliptic Curve; Ethereum Improvement Proposals, no. 2494; Ethereum Foundation: Zug, Switzerland, 2020. [Google Scholar]
  43. Barbulescu, R.; Duquesne, S. Updating Key Size Estimations for Pairings. J. Cryptol. 2019, 32, 1298–1336. [Google Scholar] [CrossRef] [Scilit]
  44. Beyne, T.; Canteaut, A.; Dinur, I.; Eichlseder, M.; Leander, G.; Leurent, G.; Naya-Plasencia, M.; Perrin, L.; Sasaki, Y.; Todo, Y.; et al. Out of Oddity—New Cryptanalytic Techniques Against Symmetric Primitives Optimized for Integrity Proof Systems. In Proceedings of the Advances in Cryptology—CRYPTO 2020; Springer: Cham, Switzerland, 2020; Volume 12172, pp. 299–328. [Google Scholar] [CrossRef] [Scilit] [PubMed]
  45. Bariant, A.; Bouvier, C.; Leurent, G.; Perrin, L. Algebraic Attacks against Some Arithmetization-Oriented Primitives. IACR Trans. Symmetric Cryptol. 2022, 2022, 73–101. [Google Scholar] [CrossRef] [Scilit]
  46. Ashur, T.; Buschman, T.; Mahzoun, M. Algebraic Cryptanalysis of the HADES Design Strategy: Application to Poseidon and Poseidon2. In Proceedings of the Information Security and Privacy—ACISP 2024; Springer: Singapore, 2024; Volume 14896, pp. 225–244. [Google Scholar] [CrossRef] [Scilit]
  47. Wahrstätter, T.; Buterin, V. EIP-7623: Increase Calldata Cost; Ethereum Improvement Proposals, no. 7623; activated on Ethereum mainnet 7 May 2025 (Pectra upgrade); Ethereum Foundation: Zug, Switzerland, 2024. [Google Scholar]
  48. Wen, H.; Stephens, J.; Chen, Y.; Ferles, K.; Pailoor, S.; Charbonnet, K.; Dillig, I.; Feng, Y. Practical Security Analysis of Zero-Knowledge Proof Circuits. In Proceedings of the 33rd USENIX Security Symposium (USENIX Security 24), Philadelphia, PA, USA, 14–16 August 2024; pp. 1471–1487. Available online: https://www.usenix.org/conference/usenixsecurity24/presentation/wen (accessed on 4 September 2026).
  49. Trail of Bits. Circomspect: A Static Analyzer and Linter for the Circom Zero-Knowledge DSL. 2022. Available online: https://github.com/trailofbits/circomspect (accessed on 26 August 2026).
  50. Pailoor, S.; Chen, Y.; Wang, F.; Rodríguez, C.; Van Geffen, J.; Morton, J.; Chu, M.; Gu, B.; Feng, Y.; Dillig, I. Automated Detection of Under-Constrained Circuits in Zero-Knowledge Proofs. Proc. ACM Program. Lang. 2023, 7, 1510–1532. [Google Scholar] [CrossRef] [Scilit]
  51. Vlasov, A.; Olson, K.; Stokes, A.; Sanso, A. EIP-2537: Precompile for BLS12-381 Curve Operations; Ethereum Improvement Proposals, no. 2537; Activated on Ethereum Mainnet 7 May 2025 (Pectra Upgrade); Ethereum Foundation: Zug, Switzerland, 2020. [Google Scholar]
Disclaimer/Publisher’s Note: The statements, opinions and data contained in all publications are solely those of the individual author(s) and contributor(s) and not of MDPI and/or the editor(s). MDPI and/or the editor(s) disclaim responsibility for any injury to people or property resulting from any ideas, methods, instructions or products referred to in the content.

Article Metrics

Citations

Article Access Statistics

Multiple requests from the same IP address are counted as one view.