@midnight-ntwrk/credential-compact 0.1.0-rc3 → 0.2.0-rc2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/CHANGELOG.md +43 -1
  2. package/README.md +47 -27
  3. package/dist/compact-build.json +6 -13
  4. package/dist/compact-value-codec.d.ts +14 -0
  5. package/dist/compact-value-codec.d.ts.map +1 -0
  6. package/dist/compact-value-codec.js +135 -0
  7. package/dist/compact-value-codec.js.map +1 -0
  8. package/dist/credentials/composable.compact +1 -3
  9. package/dist/credentials/holder-bindings.compact +11 -289
  10. package/dist/credentials/proofs.compact +85 -0
  11. package/dist/credentials/relations.compact +3 -2
  12. package/dist/credentials/signer-authorization.compact +246 -0
  13. package/dist/credentials/status-bindings.compact +0 -19
  14. package/dist/credentials/types.compact +23 -93
  15. package/dist/credentials/vc.compact +24 -3
  16. package/dist/credentials.compact +0 -1
  17. package/dist/index.d.ts +1 -1
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +1 -1
  20. package/dist/index.js.map +1 -1
  21. package/dist/managed/credentials/contract/index.d.ts +102 -196
  22. package/dist/managed/credentials/contract/index.js +746 -1342
  23. package/dist/managed/credentials/contract/index.js.map +2 -2
  24. package/package.json +12 -53
  25. package/dist/contract.d.ts +0 -2
  26. package/dist/contract.d.ts.map +0 -1
  27. package/dist/contract.js +0 -2
  28. package/dist/contract.js.map +0 -1
  29. package/dist/credentials/bindings.compact +0 -5
  30. package/dist/credentials/issue.compact +0 -91
  31. package/dist/credentials/present.compact +0 -84
  32. package/dist/credentials/protocol-support.compact +0 -7
  33. package/dist/credentials/protocols.compact +0 -125
  34. package/dist/credentials/vc-support.compact +0 -8
  35. package/dist/holder-binding/same-holder/composable.compact +0 -179
  36. package/dist/holder-binding/same-holder.compact +0 -180
  37. package/dist/holder-binding/same-holder.d.ts +0 -2
  38. package/dist/holder-binding/same-holder.d.ts.map +0 -1
  39. package/dist/holder-binding/same-holder.js +0 -2
  40. package/dist/holder-binding/same-holder.js.map +0 -1
  41. package/dist/jubjub.d.ts +0 -3
  42. package/dist/jubjub.d.ts.map +0 -1
  43. package/dist/jubjub.js +0 -6
  44. package/dist/jubjub.js.map +0 -1
  45. package/dist/managed/same-holder/contract/index.d.ts +0 -400
  46. package/dist/managed/same-holder/contract/index.js +0 -2688
  47. package/dist/managed/same-holder/contract/index.js.map +0 -8
  48. package/src/credentials/bindings.compact +0 -5
  49. package/src/credentials/composable.compact +0 -14
  50. package/src/credentials/holder-bindings.compact +0 -320
  51. package/src/credentials/issue.compact +0 -91
  52. package/src/credentials/present.compact +0 -84
  53. package/src/credentials/proofs.compact +0 -122
  54. package/src/credentials/protocol-support.compact +0 -7
  55. package/src/credentials/protocols.compact +0 -125
  56. package/src/credentials/relations.compact +0 -36
  57. package/src/credentials/status-bindings.compact +0 -60
  58. package/src/credentials/types.compact +0 -141
  59. package/src/credentials/vc-support.compact +0 -8
  60. package/src/credentials/vc.compact +0 -59
  61. package/src/credentials/vp.compact +0 -25
  62. package/src/credentials.compact +0 -20
  63. package/src/holder-binding/same-holder/composable.compact +0 -179
  64. package/src/holder-binding/same-holder.compact +0 -180
@@ -1,125 +0,0 @@
1
- // Shared protocol-envelope primitives.
2
- // These helpers are intentionally generic over issuance and presentation
3
- // choreography and remain reusable across family- and transport-specific flows.
4
- export enum HolderBindingProfile {
5
- explicitDid,
6
- secretHolder,
7
- blindedSecretHolder
8
- }
9
-
10
- // Compatibility protocol hint. Authoritative family capabilities belong on the
11
- // schema descriptor; protocol messages may carry this shape only as a transport
12
- // hint while older adapters migrate.
13
- export struct CredentialProtocolFeatures {
14
- supportsSelectiveDisclosure: Boolean,
15
- supportsPredicateProofs: Boolean,
16
- supportsVerifierScopedPseudonym: Boolean,
17
- supportsSameHolderProof: Boolean,
18
- }
19
-
20
- export pure circuit protocolFeaturesAsSchemaCapabilities(
21
- features: CredentialProtocolFeatures
22
- ): SchemaCapabilities {
23
- return SchemaCapabilities {
24
- supportsSelectiveDisclosure: features.supportsSelectiveDisclosure,
25
- supportsPredicateProofs: features.supportsPredicateProofs,
26
- supportsVerifierScopedPseudonym: features.supportsVerifierScopedPseudonym,
27
- supportsSameHolderProof: features.supportsSameHolderProof,
28
- };
29
- }
30
-
31
- export pure circuit assertProtocolFeaturesMatchSchemaCapabilities(
32
- features: CredentialProtocolFeatures,
33
- capabilities: SchemaCapabilities
34
- ): [] {
35
- assertMatchingSchemaCapabilities(
36
- protocolFeaturesAsSchemaCapabilities(features),
37
- capabilities
38
- );
39
- }
40
-
41
- export struct ProtocolMessageEnvelope {
42
- version: Uint<16>,
43
- messageId: Bytes<32>,
44
- threadId: Bytes<32>,
45
- initialMessage: Boolean,
46
- respondsToMessageId: Bytes<32>,
47
- createdAt: Uint<64>,
48
- hasExpiresAt: Boolean,
49
- expiresAt: Uint<64>,
50
- }
51
-
52
- export pure circuit noProtocolResponseReference(): Bytes<32> {
53
- return pad(32, "midnight:vc:protocol:none");
54
- }
55
-
56
- export pure circuit assertValidVerificationMethodRef(
57
- verificationMethodRef: VerificationMethodRef
58
- ): [] {
59
- assert(
60
- verificationMethodRef.methodId != pad(32, ""),
61
- "Verification method reference must be set"
62
- );
63
- }
64
-
65
- export pure circuit assertMatchingSchemaRefs(
66
- expected: SchemaRef,
67
- actual: SchemaRef
68
- ): [] {
69
- assertValidSchemaRef(expected);
70
- assertValidSchemaRef(actual);
71
- assert(
72
- expected.packageId == actual.packageId
73
- && expected.schemaId == actual.schemaId
74
- && expected.majorVersion == actual.majorVersion
75
- && expected.minorVersion == actual.minorVersion,
76
- "Schema reference mismatch"
77
- );
78
- }
79
-
80
- export pure circuit assertValidProtocolMessageEnvelope(
81
- envelope: ProtocolMessageEnvelope
82
- ): [] {
83
- const noResponse = noProtocolResponseReference();
84
- assert(envelope.version == 1, "Protocol message version mismatch");
85
- assert(envelope.messageId != noResponse, "Protocol message id must be set");
86
- assert(envelope.threadId != noResponse, "Protocol thread id must be set");
87
- if (envelope.initialMessage) {
88
- assert(
89
- envelope.respondsToMessageId == noResponse,
90
- "Initial protocol message must not reference a previous message"
91
- );
92
- } else {
93
- assert(
94
- envelope.respondsToMessageId != noResponse,
95
- "Protocol response message must reference a previous message"
96
- );
97
- }
98
- if (envelope.hasExpiresAt) {
99
- assert(
100
- envelope.expiresAt >= envelope.createdAt,
101
- "Protocol message expiration must not precede creation"
102
- );
103
- }
104
- }
105
-
106
- export pure circuit assertProtocolResponseEnvelope(
107
- requestEnvelope: ProtocolMessageEnvelope,
108
- responseEnvelope: ProtocolMessageEnvelope
109
- ): [] {
110
- assertValidProtocolMessageEnvelope(requestEnvelope);
111
- assertValidProtocolMessageEnvelope(responseEnvelope);
112
- assert(!responseEnvelope.initialMessage, "Protocol response must not be initial");
113
- assert(
114
- responseEnvelope.threadId == requestEnvelope.threadId,
115
- "Protocol response thread id does not match the request thread id"
116
- );
117
- assert(
118
- responseEnvelope.respondsToMessageId == requestEnvelope.messageId,
119
- "Protocol response does not reference the request message id"
120
- );
121
- assert(
122
- responseEnvelope.createdAt >= requestEnvelope.createdAt,
123
- "Protocol response creation time must not precede the request"
124
- );
125
- }
@@ -1,36 +0,0 @@
1
- // Generic VC↔VP linkage helpers.
2
- // This module intentionally validates only shared envelope relations; family
3
- // semantics and holder-binding witness checks stay in higher layers.
4
- module CredentialPresentationRelations<
5
- TPublicClaims,
6
- TClaimCommitments,
7
- TDisclosures,
8
- THolderBinding,
9
- TStatusBinding
10
- > {
11
- // The generic parameters are intentionally threaded through the imported
12
- // `VC<>` and `VP<>` instantiations so the relation helper stays family-typed
13
- // even though the linkage checks only read shared envelope fields.
14
- import VC<TPublicClaims, TClaimCommitments, THolderBinding, TStatusBinding> prefix VC_;
15
- import VP<TDisclosures, THolderBinding> prefix VP_;
16
-
17
- export pure circuit assertMatchingCredentialPresentation(
18
- credential: VC_Credential,
19
- presentation: VP_Presentation
20
- ): [] {
21
- // Holder-binding equality is intentionally left to the family layer because
22
- // different holder-binding profiles require different witness semantics.
23
- assert(
24
- presentation.credentialClaimRoot == credential.claimRoot,
25
- "Presentation must reference the credential claim root"
26
- );
27
- assert(
28
- presentation.issuerVerificationMethodRef.didContractAddress == credential.issuerVerificationMethodRef.didContractAddress,
29
- "Presentation issuer contract does not match credential issuer"
30
- );
31
- assert(
32
- presentation.issuerVerificationMethodRef.methodId == credential.issuerVerificationMethodRef.methodId,
33
- "Presentation issuer method reference does not match credential issuer"
34
- );
35
- }
36
- }
@@ -1,60 +0,0 @@
1
- // VC-side status-binding primitives.
2
- // Owns only the credential-embedded binding layer; proof protocols and live
3
- // registry evaluation stay in the status-registry package.
4
- export struct StatusRegistryRef {
5
- registryId: Bytes<32>,
6
- authorityVerificationMethodRef: VerificationMethodRef,
7
- }
8
-
9
- export struct NoStatusBinding {}
10
-
11
- export enum StatusType {
12
- revocationRegistry
13
- }
14
-
15
- export struct RegistryBoundStatusBinding {
16
- statusType: StatusType,
17
- registryRef: StatusRegistryRef,
18
- statusHandleCommitment: Bytes<32>,
19
- }
20
-
21
- // NOTE: `StatusType` is explicit even though the current repo only supports the
22
- // revocation-registry binding mode. Keeping it in the binding preserves an
23
- // extension seam without overloading registry ids or handle commitment shapes.
24
- export pure circuit assertValidStatusRegistryRef(
25
- registryRef: StatusRegistryRef
26
- ): [] {
27
- assert(
28
- registryRef.registryId != pad(32, ""),
29
- "Status registry id must be set"
30
- );
31
- assertValidVerificationMethodRef(registryRef.authorityVerificationMethodRef);
32
- }
33
-
34
- export pure circuit assertValidNoStatusBinding(
35
- binding: NoStatusBinding
36
- ): [] {
37
- // NOTE: NoStatusBinding is intentionally empty; this validator stays as a
38
- // symmetry point with the real binding variants.
39
- }
40
-
41
- export pure circuit assertValidRegistryBoundStatusBinding(
42
- binding: RegistryBoundStatusBinding
43
- ): [] {
44
- assert(
45
- binding.statusType == StatusType.revocationRegistry,
46
- "Registry-bound status type must be revocationRegistry"
47
- );
48
- assertValidStatusRegistryRef(binding.registryRef);
49
- assert(
50
- binding.statusHandleCommitment != pad(32, ""),
51
- "Status handle commitment must be set"
52
- );
53
- }
54
-
55
- export pure circuit registryBoundStatusBindingRoot(
56
- binding: RegistryBoundStatusBinding
57
- ): Bytes<32> {
58
- assertValidRegistryBoundStatusBinding(binding);
59
- return persistentHash<RegistryBoundStatusBinding>(binding);
60
- }
@@ -1,141 +0,0 @@
1
- export struct SchemaRef {
2
- packageId: Bytes<32>,
3
- schemaId: Bytes<32>,
4
- majorVersion: Uint<16>,
5
- minorVersion: Uint<16>,
6
- }
7
-
8
- export struct SchemaCapabilities {
9
- supportsSelectiveDisclosure: Boolean,
10
- supportsPredicateProofs: Boolean,
11
- supportsVerifierScopedPseudonym: Boolean,
12
- supportsSameHolderProof: Boolean,
13
- }
14
-
15
- export struct SchemaFamilyResolutionHint {
16
- hasResolverHint: Boolean,
17
- resolverHint: Bytes<32>,
18
- }
19
-
20
- export struct SchemaDescriptor {
21
- schema: SchemaRef,
22
- capabilities: SchemaCapabilities,
23
- familyResolutionHint: SchemaFamilyResolutionHint,
24
- }
25
-
26
- export pure circuit noSchemaFamilyResolverHint(): Bytes<32> {
27
- return pad(32, "midnight:vc:schema:no-hint");
28
- }
29
-
30
- export pure circuit assertValidSchemaRef(schema: SchemaRef): [] {
31
- assert(schema.packageId != pad(32, ""), "Schema package id must be set");
32
- assert(schema.schemaId != pad(32, ""), "Schema id must be set");
33
- assert(schema.majorVersion > 0, "Schema major version must be positive");
34
- }
35
-
36
- export pure circuit assertValidSchemaCapabilities(
37
- capabilities: SchemaCapabilities
38
- ): [] {
39
- // Boolean-only capabilities have no invalid values today. Keep this helper so
40
- // future non-boolean capability fields get one validation entry point.
41
- }
42
-
43
- export pure circuit assertValidSchemaFamilyResolutionHint(
44
- hint: SchemaFamilyResolutionHint
45
- ): [] {
46
- const noHint = noSchemaFamilyResolverHint();
47
- if (hint.hasResolverHint) {
48
- assert(hint.resolverHint != noHint, "Schema resolver hint must be set");
49
- assert(
50
- hint.resolverHint != pad(32, ""),
51
- "Schema resolver hint must not be empty"
52
- );
53
- } else {
54
- assert(
55
- hint.resolverHint == noHint,
56
- "Absent schema resolver hint must use the no-hint sentinel"
57
- );
58
- }
59
- }
60
-
61
- export pure circuit assertValidSchemaDescriptor(
62
- descriptor: SchemaDescriptor
63
- ): [] {
64
- assertValidSchemaRef(descriptor.schema);
65
- assertValidSchemaCapabilities(descriptor.capabilities);
66
- assertValidSchemaFamilyResolutionHint(descriptor.familyResolutionHint);
67
- }
68
-
69
- export pure circuit assertMatchingSchemaCapabilities(
70
- expected: SchemaCapabilities,
71
- actual: SchemaCapabilities
72
- ): [] {
73
- assert(
74
- expected.supportsSelectiveDisclosure == actual.supportsSelectiveDisclosure
75
- && expected.supportsPredicateProofs == actual.supportsPredicateProofs
76
- && expected.supportsVerifierScopedPseudonym == actual.supportsVerifierScopedPseudonym
77
- && expected.supportsSameHolderProof == actual.supportsSameHolderProof,
78
- "Schema capabilities mismatch"
79
- );
80
- }
81
-
82
- export struct VerificationMethodRef {
83
- didContractAddress: ContractAddress,
84
- methodId: Bytes<32>,
85
- }
86
-
87
- export struct NoPublicClaims {
88
- }
89
-
90
- export struct NoClaimCommitments {
91
- }
92
-
93
- export struct Signature {
94
- r: JubjubPoint,
95
- s: Field,
96
- }
97
-
98
- export struct ExplicitHolderBinding {
99
- holderVerificationMethodRef: VerificationMethodRef,
100
- }
101
-
102
- export struct JubjubHolderBinding {
103
- // Legacy compatibility/minimal holder binding.
104
- // This binds the VC/VP to a specific Jubjub public key, but it is not the
105
- // recommended public profile for new DID-shaped flows.
106
- // Proof-of-possession still depends on validating the presentation Proof
107
- // alongside this binding.
108
- holderPublicKey: JubjubPoint,
109
- }
110
-
111
- export struct OffchainMidnightHolderBinding {
112
- // Preferred lightweight DID-shaped binding for offchain/prototype flows.
113
- // This adds DID-shaped metadata for prototype offchain Midnight DID flows.
114
- // It does not by itself prove that holderPublicKey is the key published in
115
- // the offchain DID state; callers still need the surrounding DID semantics.
116
- holderDidStateHash: Bytes<32>,
117
- holderMethodId: Bytes<32>,
118
- holderPublicKey: JubjubPoint,
119
- }
120
-
121
- export struct SecretHolderBinding {
122
- holderSecretCommitment: Bytes<32>,
123
- requestChallengeResponse: Bytes<32>,
124
- }
125
-
126
- export struct BlindedSecretHolderBinding {
127
- blindedHolderSecretCommitment: Bytes<32>,
128
- issuerNonce: Bytes<32>,
129
- requestChallengeResponse: Bytes<32>,
130
- }
131
-
132
- // Proof is kept separate from the VC/VP body on purpose.
133
- // The body is the semantic payload; the proof is the cryptographic artifact
134
- // over that payload plus interaction context.
135
- export struct Proof {
136
- signerVerificationMethodRef: VerificationMethodRef,
137
- createdAt: Uint<64>,
138
- challengeHash: Bytes<32>,
139
- publicKey: JubjubPoint,
140
- signature: Signature,
141
- }
@@ -1,8 +0,0 @@
1
- // Shared VC surface for credential families that need envelope types,
2
- // proof helpers, and proof-bound validation rules.
3
-
4
- include "./types";
5
- include "./proofs";
6
- include "./vc";
7
- include "./vp";
8
- include "./relations";
@@ -1,59 +0,0 @@
1
- // Thin VC envelope surface.
2
- // Owns credential-local structure, body-root derivation, and issuer-proof
3
- // verification. Family-specific claim validation stays outside this module.
4
- module VC<TPublicClaims, TClaimCommitments, THolderBinding, TStatusBinding> {
5
- export struct Credential {
6
- version: Uint<16>,
7
- schema: SchemaRef,
8
- issuerVerificationMethodRef: VerificationMethodRef,
9
- holderBinding: THolderBinding,
10
- statusBinding: TStatusBinding,
11
- issuedAt: Uint<64>,
12
- hasExpiration: Boolean,
13
- expiresAt: Uint<64>,
14
- // Direct values intentionally carried in the signed credential body.
15
- claims: TPublicClaims,
16
- // Commitment digests for private and predicate-only claim values.
17
- claimCommitments: TClaimCommitments,
18
- claimRoot: Bytes<32>,
19
- }
20
-
21
- export pure circuit credentialBodyRoot(credential: Credential): Bytes<32> {
22
- return persistentHash<Credential>(credential);
23
- }
24
-
25
- export pure circuit assertValidCredentialEnvelope(
26
- credential: Credential,
27
- expectedClaimRoot: Bytes<32>
28
- ): [] {
29
- assert(credential.version == 1, "Credential version mismatch");
30
- assert(credential.claimRoot == expectedClaimRoot, "Credential claim root mismatch");
31
- if (credential.hasExpiration) {
32
- assert(credential.expiresAt >= credential.issuedAt, "Expiration must not precede issuance");
33
- }
34
- }
35
-
36
- export pure circuit assertValidCredentialProof(
37
- credential: Credential,
38
- proof: Proof
39
- ): [] {
40
- const bodyRoot: Bytes<32> = credentialBodyRoot(credential);
41
- assertValidCredentialProofForBodyRoot(credential, proof, bodyRoot);
42
- }
43
-
44
- export pure circuit assertValidCredentialProofForBodyRoot(
45
- credential: Credential,
46
- proof: Proof,
47
- bodyRoot: Bytes<32>
48
- ): [] {
49
- assert(
50
- credential.issuerVerificationMethodRef.didContractAddress == proof.signerVerificationMethodRef.didContractAddress,
51
- "Issuer proof contract address does not match issuer verification method"
52
- );
53
- assert(
54
- credential.issuerVerificationMethodRef.methodId == proof.signerVerificationMethodRef.methodId,
55
- "Issuer proof method reference does not match issuer verification method"
56
- );
57
- assertValidIssuanceContextProof(bodyRoot, proof);
58
- }
59
- }
@@ -1,25 +0,0 @@
1
- // Thin VP envelope surface.
2
- // Owns presentation-local structure and body-root derivation. VC↔VP linkage
3
- // and holder-binding equality stay outside this module.
4
- module VP<TDisclosures, THolderBinding> {
5
- export struct Presentation {
6
- version: Uint<16>,
7
- schema: SchemaRef,
8
- credentialClaimRoot: Bytes<32>,
9
- issuerVerificationMethodRef: VerificationMethodRef,
10
- holderBinding: THolderBinding,
11
- disclosed: TDisclosures,
12
- }
13
-
14
- export pure circuit presentationBodyRoot(presentation: Presentation): Bytes<32> {
15
- return persistentHash<Presentation>(presentation);
16
- }
17
-
18
- export pure circuit assertValidPresentationEnvelope(
19
- presentation: Presentation
20
- ): [] {
21
- // VC/VP linkage now lives in `relations.compact`; the thin VP surface only
22
- // owns presentation-local envelope invariants.
23
- assert(presentation.version == 1, "Presentation version mismatch");
24
- }
25
- }
@@ -1,20 +0,0 @@
1
- // This file is part of midnightntwrk/midnight-did.
2
- // Copyright (C) 2026 Midnight Foundation
3
- // SPDX-License-Identifier: Apache-2.0
4
- // Licensed under the Apache License, Version 2.0 (the "License");
5
- // you may not use this file except in compliance with the License.
6
- // You may obtain a copy of the License at
7
- //
8
- // http://www.apache.org/licenses/LICENSE-2.0
9
- //
10
- // Unless required by applicable law or agreed to in writing, software
11
- // distributed under the License is distributed on an "AS IS" BASIS,
12
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- // See the License for the specific language governing permissions and
14
- // limitations under the License.
15
-
16
- pragma language_version >= 0.20;
17
-
18
- import CompactStandardLibrary;
19
-
20
- include "./credentials/composable";
@@ -1,179 +0,0 @@
1
- // This file is part of midnightntwrk/midnight-did.
2
- // Copyright (C) 2026 Midnight Foundation
3
- // SPDX-License-Identifier: Apache-2.0
4
- // Licensed under the Apache License, Version 2.0 (the "License");
5
- // you may not use this file except in compliance with the License.
6
- // You may obtain a copy of the License at
7
- //
8
- // http://www.apache.org/licenses/LICENSE-2.0
9
- //
10
- // Unless required by applicable law or agreed to in writing, software
11
- // distributed under the License is distributed on an "AS IS" BASIS,
12
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- // See the License for the specific language governing permissions and
14
- // limitations under the License.
15
-
16
- // Composition-safe entry point for Layer 3 contracts. The importing contract
17
- // must include `credentials/bindings` or
18
- // `credentials/composable` before including this file.
19
-
20
-
21
- // Capability package: prove that multiple holder bindings are satisfied by the
22
- // same hidden holder secret witness under one verifier session challenge.
23
-
24
- export pure circuit assertSameSecretHolderBindingWitnesses(
25
- firstBinding: SecretHolderBinding,
26
- secondBinding: SecretHolderBinding,
27
- verifierChallengeHash: Bytes<32>,
28
- holderSecret: Bytes<32>,
29
- firstOpening: Bytes<32>,
30
- secondOpening: Bytes<32>
31
- ): [] {
32
- assert(
33
- firstBinding.holderSecretCommitment != secondBinding.holderSecretCommitment,
34
- "Same-holder proof requires two distinct credential bindings"
35
- );
36
- assertSecretHolderBindingWitness(
37
- firstBinding,
38
- verifierChallengeHash,
39
- holderSecret,
40
- firstOpening
41
- );
42
- assertSecretHolderBindingWitness(
43
- secondBinding,
44
- verifierChallengeHash,
45
- holderSecret,
46
- secondOpening
47
- );
48
- }
49
-
50
- // Three-credential same-holder composition for plain secret bindings.
51
- // This keeps the reusable capability explicit and bounded instead of
52
- // prematurely introducing a generic "bundle" abstraction.
53
- export pure circuit assertSameSecretHolderBindingWitnesses3(
54
- firstBinding: SecretHolderBinding,
55
- secondBinding: SecretHolderBinding,
56
- thirdBinding: SecretHolderBinding,
57
- verifierChallengeHash: Bytes<32>,
58
- holderSecret: Bytes<32>,
59
- firstOpening: Bytes<32>,
60
- secondOpening: Bytes<32>,
61
- thirdOpening: Bytes<32>
62
- ): [] {
63
- assert(
64
- firstBinding.holderSecretCommitment != secondBinding.holderSecretCommitment,
65
- "Same-holder proof requires distinct first and second credential bindings"
66
- );
67
- assert(
68
- firstBinding.holderSecretCommitment != thirdBinding.holderSecretCommitment,
69
- "Same-holder proof requires distinct first and third credential bindings"
70
- );
71
- assert(
72
- secondBinding.holderSecretCommitment != thirdBinding.holderSecretCommitment,
73
- "Same-holder proof requires distinct second and third credential bindings"
74
- );
75
-
76
- assertSecretHolderBindingWitness(
77
- firstBinding,
78
- verifierChallengeHash,
79
- holderSecret,
80
- firstOpening
81
- );
82
- assertSecretHolderBindingWitness(
83
- secondBinding,
84
- verifierChallengeHash,
85
- holderSecret,
86
- secondOpening
87
- );
88
- assertSecretHolderBindingWitness(
89
- thirdBinding,
90
- verifierChallengeHash,
91
- holderSecret,
92
- thirdOpening
93
- );
94
- }
95
-
96
- // Same-holder composition for blinded bindings. The caller supplies the same
97
- // hidden holder witness together with the binding-specific opening and blinding
98
- // factor for each independently issued credential.
99
- export pure circuit assertSameBlindedSecretHolderBindingWitnesses(
100
- firstBinding: BlindedSecretHolderBinding,
101
- secondBinding: BlindedSecretHolderBinding,
102
- verifierChallengeHash: Bytes<32>,
103
- holderSecret: Bytes<32>,
104
- firstOpening: Bytes<32>,
105
- firstBlindingFactor: Bytes<32>,
106
- secondOpening: Bytes<32>,
107
- secondBlindingFactor: Bytes<32>
108
- ): [] {
109
- assert(
110
- firstBinding.blindedHolderSecretCommitment != secondBinding.blindedHolderSecretCommitment,
111
- "Same-holder proof requires two distinct credential bindings"
112
- );
113
- assertBlindedSecretHolderBindingWitness(
114
- firstBinding,
115
- verifierChallengeHash,
116
- holderSecret,
117
- firstOpening,
118
- firstBlindingFactor
119
- );
120
- assertBlindedSecretHolderBindingWitness(
121
- secondBinding,
122
- verifierChallengeHash,
123
- holderSecret,
124
- secondOpening,
125
- secondBlindingFactor
126
- );
127
- }
128
-
129
- // Three-credential same-holder composition for blinded bindings. This is the
130
- // next bounded step after the two-credential primitive and is sufficient for
131
- // staged business flows such as travel or onboarding checks.
132
- export pure circuit assertSameBlindedSecretHolderBindingWitnesses3(
133
- firstBinding: BlindedSecretHolderBinding,
134
- secondBinding: BlindedSecretHolderBinding,
135
- thirdBinding: BlindedSecretHolderBinding,
136
- verifierChallengeHash: Bytes<32>,
137
- holderSecret: Bytes<32>,
138
- firstOpening: Bytes<32>,
139
- firstBlindingFactor: Bytes<32>,
140
- secondOpening: Bytes<32>,
141
- secondBlindingFactor: Bytes<32>,
142
- thirdOpening: Bytes<32>,
143
- thirdBlindingFactor: Bytes<32>
144
- ): [] {
145
- assert(
146
- firstBinding.blindedHolderSecretCommitment != secondBinding.blindedHolderSecretCommitment,
147
- "Same-holder proof requires distinct first and second credential bindings"
148
- );
149
- assert(
150
- firstBinding.blindedHolderSecretCommitment != thirdBinding.blindedHolderSecretCommitment,
151
- "Same-holder proof requires distinct first and third credential bindings"
152
- );
153
- assert(
154
- secondBinding.blindedHolderSecretCommitment != thirdBinding.blindedHolderSecretCommitment,
155
- "Same-holder proof requires distinct second and third credential bindings"
156
- );
157
-
158
- assertBlindedSecretHolderBindingWitness(
159
- firstBinding,
160
- verifierChallengeHash,
161
- holderSecret,
162
- firstOpening,
163
- firstBlindingFactor
164
- );
165
- assertBlindedSecretHolderBindingWitness(
166
- secondBinding,
167
- verifierChallengeHash,
168
- holderSecret,
169
- secondOpening,
170
- secondBlindingFactor
171
- );
172
- assertBlindedSecretHolderBindingWitness(
173
- thirdBinding,
174
- verifierChallengeHash,
175
- holderSecret,
176
- thirdOpening,
177
- thirdBlindingFactor
178
- );
179
- }