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

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,30 +1,20 @@
1
- // Holder-binding and holder-witness primitives.
2
- // This file groups the reusable binding checks for explicit DID, Jubjub,
3
- // offchain DID, secret-holder, and blinded-secret-holder profiles.
4
- // =====================
5
- // Explicit and Jubjub-backed holder bindings
6
- // =====================
1
+ // Explicit holder-binding primitives.
7
2
  export pure circuit assertValidExplicitHolderBinding(
8
3
  binding: ExplicitHolderBinding
9
4
  ): [] {
10
- assert(
11
- binding.holderVerificationMethodRef.didContractAddress.bytes != pad(32, ""),
12
- "Explicit holder binding DID contract address must be set"
13
- );
14
- assert(
15
- binding.holderVerificationMethodRef.methodId != pad(32, ""),
16
- "Explicit holder binding method reference must be set"
17
- );
5
+ assertValidVerificationMethodRef(binding.holderVerificationMethodRef);
18
6
  }
19
7
 
20
8
  export pure circuit assertMatchingExplicitHolderBindings(
21
9
  credentialBinding: ExplicitHolderBinding,
22
10
  presentationBinding: ExplicitHolderBinding
23
11
  ): [] {
12
+ assertValidExplicitHolderBinding(credentialBinding);
13
+ assertValidExplicitHolderBinding(presentationBinding);
24
14
  assert(
25
- presentationBinding.holderVerificationMethodRef.didContractAddress
26
- == credentialBinding.holderVerificationMethodRef.didContractAddress,
27
- "Presentation holder contract does not match credential holder binding"
15
+ presentationBinding.holderVerificationMethodRef.controllerAddress
16
+ == credentialBinding.holderVerificationMethodRef.controllerAddress,
17
+ "Presentation holder controller does not match credential holder binding"
28
18
  );
29
19
  assert(
30
20
  presentationBinding.holderVerificationMethodRef.methodId
@@ -37,9 +27,11 @@ export pure circuit assertProofMatchesExplicitHolderBinding(
37
27
  binding: ExplicitHolderBinding,
38
28
  presentationProof: Proof
39
29
  ): [] {
30
+ assertValidExplicitHolderBinding(binding);
31
+ assertValidVerificationMethodRef(presentationProof.signerVerificationMethodRef);
40
32
  assert(
41
- binding.holderVerificationMethodRef.didContractAddress
42
- == presentationProof.signerVerificationMethodRef.didContractAddress,
33
+ binding.holderVerificationMethodRef.controllerAddress
34
+ == presentationProof.signerVerificationMethodRef.controllerAddress,
43
35
  "Presentation proof signer must match holder binding"
44
36
  );
45
37
  assert(
@@ -48,273 +40,3 @@ export pure circuit assertProofMatchesExplicitHolderBinding(
48
40
  "Presentation proof signer method reference must match holder binding"
49
41
  );
50
42
  }
51
-
52
- export pure circuit assertValidJubjubHolderBinding(
53
- binding: JubjubHolderBinding
54
- ): [] {
55
- // This is only a sentinel check that the binding is populated.
56
- // The helper remains useful for the legacy compatibility profile and as a
57
- // building block inside richer DID-shaped bindings.
58
- // Callers still need assertValidPresentationContextProof(...) or an
59
- // equivalent proof verification path to establish proof-of-possession.
60
- assert(
61
- jubjubPointX(binding.holderPublicKey) != 0 as Field ||
62
- jubjubPointY(binding.holderPublicKey) != 0 as Field,
63
- "Jubjub holder binding public key must be set"
64
- );
65
- }
66
-
67
- export pure circuit assertMatchingJubjubHolderBindings(
68
- credentialBinding: JubjubHolderBinding,
69
- presentationBinding: JubjubHolderBinding
70
- ): [] {
71
- assert(
72
- jubjubPointX(presentationBinding.holderPublicKey)
73
- == jubjubPointX(credentialBinding.holderPublicKey) &&
74
- jubjubPointY(presentationBinding.holderPublicKey)
75
- == jubjubPointY(credentialBinding.holderPublicKey),
76
- "Presentation Jubjub holder key does not match the credential holder binding"
77
- );
78
- }
79
-
80
- export pure circuit assertProofMatchesJubjubHolderBinding(
81
- binding: JubjubHolderBinding,
82
- presentationProof: Proof
83
- ): [] {
84
- assert(
85
- jubjubPointX(binding.holderPublicKey)
86
- == jubjubPointX(presentationProof.publicKey) &&
87
- jubjubPointY(binding.holderPublicKey)
88
- == jubjubPointY(presentationProof.publicKey),
89
- "Presentation proof public key must match the Jubjub holder binding"
90
- );
91
- }
92
-
93
- export pure circuit assertValidOffchainMidnightHolderBinding(
94
- binding: OffchainMidnightHolderBinding
95
- ): [] {
96
- // This validates presence and consistency only for the preferred lightweight
97
- // DID-shaped offchain profile.
98
- // It does not prove that holderPublicKey is the verification method
99
- // published under holderMethodId in the referenced offchain DID state.
100
- assert(
101
- binding.holderDidStateHash != pad(32, ""),
102
- "Offchain Midnight holder state hash must be set"
103
- );
104
- assert(
105
- binding.holderMethodId != pad(32, ""),
106
- "Offchain Midnight holder method id must be set"
107
- );
108
- const jubjubBinding: JubjubHolderBinding = JubjubHolderBinding {
109
- holderPublicKey: binding.holderPublicKey
110
- };
111
- assertValidJubjubHolderBinding(jubjubBinding);
112
- }
113
-
114
- export pure circuit assertMatchingOffchainMidnightHolderBindings(
115
- credentialBinding: OffchainMidnightHolderBinding,
116
- presentationBinding: OffchainMidnightHolderBinding
117
- ): [] {
118
- assert(
119
- presentationBinding.holderDidStateHash
120
- == credentialBinding.holderDidStateHash,
121
- "Offchain Midnight holder state hash does not match the credential holder binding"
122
- );
123
- assert(
124
- presentationBinding.holderMethodId
125
- == credentialBinding.holderMethodId,
126
- "Offchain Midnight holder method id does not match the credential holder binding"
127
- );
128
- const credentialJubjubBinding: JubjubHolderBinding = JubjubHolderBinding {
129
- holderPublicKey: credentialBinding.holderPublicKey
130
- };
131
- const presentationJubjubBinding: JubjubHolderBinding = JubjubHolderBinding {
132
- holderPublicKey: presentationBinding.holderPublicKey
133
- };
134
- assertMatchingJubjubHolderBindings(
135
- credentialJubjubBinding,
136
- presentationJubjubBinding
137
- );
138
- }
139
-
140
- export pure circuit assertProofMatchesOffchainMidnightHolderBinding(
141
- binding: OffchainMidnightHolderBinding,
142
- presentationProof: Proof
143
- ): [] {
144
- const jubjubBinding: JubjubHolderBinding = JubjubHolderBinding {
145
- holderPublicKey: binding.holderPublicKey
146
- };
147
- assertProofMatchesJubjubHolderBinding(jubjubBinding, presentationProof);
148
- }
149
-
150
- // =====================
151
- // Secret-holder bindings and derived pseudonyms
152
- // =====================
153
- export pure circuit noSecretHolderChallengeResponse(): Bytes<32> {
154
- return pad(32, "midnight:vc:no-holder-response");
155
- }
156
-
157
- export pure circuit secretHolderBindingCommitment(
158
- holderSecret: Bytes<32>,
159
- opening: Bytes<32>
160
- ): Bytes<32> {
161
- return persistentCommit<Bytes<32>>(holderSecret, opening);
162
- }
163
-
164
- export pure circuit secretHolderBindingChallengeResponse(
165
- holderSecret: Bytes<32>,
166
- verifierChallengeHash: Bytes<32>
167
- ): Bytes<32> {
168
- return persistentHash<Vector<3, Bytes<32>>>([
169
- pad(32, "midnight:vc:holder-chall"),
170
- holderSecret,
171
- verifierChallengeHash
172
- ]);
173
- }
174
-
175
- export pure circuit verifierScopedPseudonym(
176
- holderSecret: Bytes<32>,
177
- verifierDomainHash: Bytes<32>
178
- ): Bytes<32> {
179
- return persistentHash<Vector<3, Bytes<32>>>([
180
- pad(32, "midnight:vc:holder-pseudonym"),
181
- holderSecret,
182
- verifierDomainHash
183
- ]);
184
- }
185
-
186
- export pure circuit assertVerifierScopedPseudonym(
187
- pseudonym: Bytes<32>,
188
- holderSecret: Bytes<32>,
189
- verifierDomainHash: Bytes<32>
190
- ): [] {
191
- assert(
192
- pseudonym == verifierScopedPseudonym(holderSecret, verifierDomainHash),
193
- "Verifier-scoped pseudonym does not match the holder secret and verifier domain"
194
- );
195
- }
196
-
197
- export pure circuit blindedSecretHolderCommitment(
198
- holderSecretCommitment: Bytes<32>,
199
- issuerNonce: Bytes<32>,
200
- blindingFactor: Bytes<32>
201
- ): Bytes<32> {
202
- // NOTE: This remains a hash-based compatibility commitment today. The
203
- // breaking `persistentCommit` migration is tracked separately and should not
204
- // be rolled in silently with source-style or purity cleanups.
205
- return persistentHash<Vector<4, Bytes<32>>>([
206
- pad(32, "midnight:vc:blind-holder"),
207
- holderSecretCommitment,
208
- issuerNonce,
209
- blindingFactor
210
- ]);
211
- }
212
-
213
- export pure circuit assertValidSecretHolderCredentialBinding(
214
- binding: SecretHolderBinding
215
- ): [] {
216
- assert(
217
- binding.requestChallengeResponse == noSecretHolderChallengeResponse(),
218
- "Credential secret holder binding must not embed a request challenge response"
219
- );
220
- }
221
-
222
- export pure circuit assertValidSecretHolderPresentationBinding(
223
- binding: SecretHolderBinding
224
- ): [] {
225
- assert(
226
- binding.requestChallengeResponse != noSecretHolderChallengeResponse(),
227
- "Presentation secret holder binding must include a request challenge response"
228
- );
229
- }
230
-
231
- export pure circuit assertMatchingSecretHolderBindings(
232
- credentialBinding: SecretHolderBinding,
233
- presentationBinding: SecretHolderBinding
234
- ): [] {
235
- assert(
236
- credentialBinding.holderSecretCommitment == presentationBinding.holderSecretCommitment,
237
- "Presentation holder secret commitment does not match the credential holder binding"
238
- );
239
- }
240
-
241
- export pure circuit assertValidBlindedSecretHolderCredentialBinding(
242
- binding: BlindedSecretHolderBinding
243
- ): [] {
244
- assert(
245
- binding.requestChallengeResponse == noSecretHolderChallengeResponse(),
246
- "Credential blinded holder binding must not embed a request challenge response"
247
- );
248
- }
249
-
250
- export pure circuit assertValidBlindedSecretHolderPresentationBinding(
251
- binding: BlindedSecretHolderBinding
252
- ): [] {
253
- assert(
254
- binding.requestChallengeResponse != noSecretHolderChallengeResponse(),
255
- "Presentation blinded holder binding must include a request challenge response"
256
- );
257
- }
258
-
259
- export pure circuit assertMatchingBlindedSecretHolderBindings(
260
- credentialBinding: BlindedSecretHolderBinding,
261
- presentationBinding: BlindedSecretHolderBinding
262
- ): [] {
263
- assert(
264
- credentialBinding.blindedHolderSecretCommitment
265
- == presentationBinding.blindedHolderSecretCommitment,
266
- "Presentation blinded holder commitment does not match the credential holder binding"
267
- );
268
- assert(
269
- credentialBinding.issuerNonce == presentationBinding.issuerNonce,
270
- "Presentation issuer nonce does not match the credential holder binding"
271
- );
272
- }
273
-
274
- // =====================
275
- // Witness validation and recomputation helpers
276
- // =====================
277
- // NOTE: these helpers validate caller-supplied witness material passed as
278
- // ordinary parameters. They do not perform Compact `witness` reads themselves.
279
- export pure circuit assertSecretHolderBindingWitness(
280
- binding: SecretHolderBinding,
281
- verifierChallengeHash: Bytes<32>,
282
- holderSecret: Bytes<32>,
283
- opening: Bytes<32>
284
- ): [] {
285
- assert(
286
- secretHolderBindingCommitment(holderSecret, opening) == binding.holderSecretCommitment,
287
- "Holder secret witness does not match the holder-binding commitment"
288
- );
289
- assert(
290
- secretHolderBindingChallengeResponse(holderSecret, verifierChallengeHash)
291
- == binding.requestChallengeResponse,
292
- "Holder secret challenge response does not match the verifier challenge"
293
- );
294
- }
295
-
296
- export pure circuit assertBlindedSecretHolderBindingWitness(
297
- binding: BlindedSecretHolderBinding,
298
- verifierChallengeHash: Bytes<32>,
299
- holderSecret: Bytes<32>,
300
- opening: Bytes<32>,
301
- blindingFactor: Bytes<32>
302
- ): [] {
303
- const holderCommitment: Bytes<32> = secretHolderBindingCommitment(
304
- holderSecret,
305
- opening
306
- );
307
- assert(
308
- blindedSecretHolderCommitment(
309
- holderCommitment,
310
- binding.issuerNonce,
311
- blindingFactor
312
- ) == binding.blindedHolderSecretCommitment,
313
- "Blinded holder commitment does not match the hidden holder secret witness"
314
- );
315
- assert(
316
- secretHolderBindingChallengeResponse(holderSecret, verifierChallengeHash)
317
- == binding.requestChallengeResponse,
318
- "Blinded holder challenge response does not match the verifier challenge"
319
- );
320
- }
@@ -1,11 +1,43 @@
1
1
  // Context-tagged proof primitives.
2
2
  // This file owns signature verification plus the shared proof payload/challenge
3
3
  // derivation rules for generic issuance and presentation flows.
4
+ pure circuit assertMatchingJubjubPoints(
5
+ expected: JubjubPoint,
6
+ actual: JubjubPoint
7
+ ): [] {
8
+ assert(
9
+ jubjubPointX(expected) == jubjubPointX(actual)
10
+ && jubjubPointY(expected) == jubjubPointY(actual),
11
+ "Jubjub points do not match"
12
+ );
13
+ }
14
+
15
+ pure circuit assertUsableJubjubPoint(point: JubjubPoint): [] {
16
+ assert(
17
+ jubjubPointX(point) != 0 || jubjubPointY(point) != 1,
18
+ "Jubjub point must not be the identity point"
19
+ );
20
+
21
+ // (q + 1) / 8 followed by the cofactor projects onto the prime-order
22
+ // subgroup. Equality rejects a torsion component; ecMul constrains the input
23
+ // to the curve.
24
+ const subgroupProjection: JubjubPoint = ecMul(
25
+ ecMul(
26
+ point,
27
+ 819310549611346726241370945440405716213240158234039660170669895299022906775 as Field
28
+ ),
29
+ 8
30
+ );
31
+ assertMatchingJubjubPoints(point, subgroupProjection);
32
+ }
33
+
4
34
  export pure circuit verifySignature(
5
35
  pk: JubjubPoint,
6
36
  signature: Signature,
7
37
  challenge: Field
8
38
  ): Boolean {
39
+ assertUsableJubjubPoint(pk);
40
+ assertUsableJubjubPoint(signature.r);
9
41
  const leftSide: JubjubPoint = ecMulGenerator(signature.s);
10
42
  const cPk: JubjubPoint = ecMul(pk, challenge);
11
43
  const rightSide: JubjubPoint = ecAdd(signature.r, cPk);
@@ -29,6 +61,14 @@ export pure circuit presentationContextTag(): Bytes<32> {
29
61
  return pad(32, "midnight:vc:presentation");
30
62
  }
31
63
 
64
+ export pure circuit signerAuthorizationContextTag(): Bytes<32> {
65
+ return pad(32, "midnight:vc:signer-auth:v1");
66
+ }
67
+
68
+ export pure circuit verifierRequestContextTag(): Bytes<32> {
69
+ return pad(32, "midnight:vc:verifier-req:v1");
70
+ }
71
+
32
72
  // =====================
33
73
  // Internal payload and challenge derivation
34
74
  // =====================
@@ -63,6 +103,7 @@ pure circuit assertValidProofForContext(
63
103
  contextTag: Bytes<32>,
64
104
  proof: Proof
65
105
  ): [] {
106
+ assertValidVerificationMethodRef(proof.signerVerificationMethodRef);
66
107
  assert(
67
108
  verifySignature(
68
109
  proof.publicKey,
@@ -101,6 +142,28 @@ export pure circuit presentationProofChallenge(
101
142
  return proofChallengeForContext(bodyRoot, presentationContextTag(), proof);
102
143
  }
103
144
 
145
+ export pure circuit signerAuthorizationProofChallenge(
146
+ bodyRoot: Bytes<32>,
147
+ proof: Proof
148
+ ): Field {
149
+ return proofChallengeForContext(
150
+ bodyRoot,
151
+ signerAuthorizationContextTag(),
152
+ proof
153
+ );
154
+ }
155
+
156
+ export pure circuit verifierRequestProofChallenge(
157
+ requestScopeCommitment: Bytes<32>,
158
+ proof: Proof
159
+ ): Field {
160
+ return proofChallengeForContext(
161
+ requestScopeCommitment,
162
+ verifierRequestContextTag(),
163
+ proof
164
+ );
165
+ }
166
+
104
167
  // =====================
105
168
  // Public context-specific proof entrypoints
106
169
  // =====================
@@ -120,3 +183,25 @@ export pure circuit assertValidPresentationContextProof(
120
183
  ): [] {
121
184
  assertValidProofForContext(bodyRoot, presentationContextTag(), proof);
122
185
  }
186
+
187
+ export pure circuit assertValidSignerAuthorizationContextProof(
188
+ bodyRoot: Bytes<32>,
189
+ proof: Proof
190
+ ): [] {
191
+ assertValidProofForContext(
192
+ bodyRoot,
193
+ signerAuthorizationContextTag(),
194
+ proof
195
+ );
196
+ }
197
+
198
+ export pure circuit assertValidVerifierRequestContextProof(
199
+ requestScopeCommitment: Bytes<32>,
200
+ proof: Proof
201
+ ): [] {
202
+ assertValidProofForContext(
203
+ requestScopeCommitment,
204
+ verifierRequestContextTag(),
205
+ proof
206
+ );
207
+ }
@@ -20,13 +20,14 @@ module CredentialPresentationRelations<
20
20
  ): [] {
21
21
  // Holder-binding equality is intentionally left to the family layer because
22
22
  // different holder-binding profiles require different witness semantics.
23
+ assertMatchingSchemaRefs(credential.schema, presentation.schema);
23
24
  assert(
24
25
  presentation.credentialClaimRoot == credential.claimRoot,
25
26
  "Presentation must reference the credential claim root"
26
27
  );
27
28
  assert(
28
- presentation.issuerVerificationMethodRef.didContractAddress == credential.issuerVerificationMethodRef.didContractAddress,
29
- "Presentation issuer contract does not match credential issuer"
29
+ presentation.issuerVerificationMethodRef.controllerAddress == credential.issuerVerificationMethodRef.controllerAddress,
30
+ "Presentation issuer controller does not match credential issuer"
30
31
  );
31
32
  assert(
32
33
  presentation.issuerVerificationMethodRef.methodId == credential.issuerVerificationMethodRef.methodId,
@@ -0,0 +1,246 @@
1
+ // Source-neutral signer authorization primitives.
2
+ // Applications may install descriptors through local governance or verify a
3
+ // domain-separated authority proof before materializing the same descriptor.
4
+
5
+ export enum SignerRole {
6
+ issuer,
7
+ verifier
8
+ }
9
+
10
+ export enum AuthorizationState {
11
+ active,
12
+ suspended,
13
+ revoked
14
+ }
15
+
16
+ export enum VerificationRelationship {
17
+ assertionMethod,
18
+ authentication,
19
+ capabilityInvocation
20
+ }
21
+
22
+ export struct AuthorizedSignerDescriptor {
23
+ version: Uint<16>,
24
+ authorizationId: Bytes<32>,
25
+ decisionSequence: Uint<64>,
26
+ state: AuthorizationState,
27
+ role: SignerRole,
28
+ signerVerificationMethodRef: VerificationMethodRef,
29
+ signerPublicKey: JubjubPoint,
30
+ didStateVersion: Uint<64>,
31
+ verificationRelationship: VerificationRelationship,
32
+ scopeCommitment: Bytes<32>,
33
+ policyCommitment: Bytes<32>,
34
+ }
35
+
36
+ export struct SignerAuthorizationAuthority {
37
+ domainCommitment: Bytes<32>,
38
+ verificationMethodRef: VerificationMethodRef,
39
+ publicKey: JubjubPoint,
40
+ }
41
+
42
+ export pure circuit assertValidAuthorizedSignerDescriptor(
43
+ descriptor: AuthorizedSignerDescriptor
44
+ ): [] {
45
+ assert(descriptor.version == 1, "Signer authorization version mismatch");
46
+ assert(
47
+ descriptor.authorizationId != pad(32, ""),
48
+ "Signer authorization id must be set"
49
+ );
50
+ assert(
51
+ descriptor.decisionSequence > 0,
52
+ "Signer authorization decision sequence must be positive"
53
+ );
54
+ assertValidVerificationMethodRef(descriptor.signerVerificationMethodRef);
55
+ assertUsableJubjubPoint(descriptor.signerPublicKey);
56
+ assert(
57
+ descriptor.didStateVersion > 0,
58
+ "Signer authorization DID state version must be positive"
59
+ );
60
+ assert(
61
+ descriptor.scopeCommitment != pad(32, ""),
62
+ "Signer authorization scope commitment must be set"
63
+ );
64
+ assert(
65
+ descriptor.policyCommitment != pad(32, ""),
66
+ "Signer authorization policy commitment must be set"
67
+ );
68
+
69
+ if (descriptor.role == SignerRole.issuer) {
70
+ assert(
71
+ descriptor.verificationRelationship
72
+ == VerificationRelationship.assertionMethod,
73
+ "Issuer authorization requires assertionMethod"
74
+ );
75
+ } else {
76
+ assert(
77
+ descriptor.verificationRelationship
78
+ == VerificationRelationship.authentication
79
+ || descriptor.verificationRelationship
80
+ == VerificationRelationship.capabilityInvocation,
81
+ "Verifier authorization requires authentication or capabilityInvocation"
82
+ );
83
+ }
84
+ }
85
+
86
+ export pure circuit authorizedSignerDescriptorRoot(
87
+ descriptor: AuthorizedSignerDescriptor
88
+ ): Bytes<32> {
89
+ assertValidAuthorizedSignerDescriptor(descriptor);
90
+ return authorizedSignerDescriptorHash(descriptor);
91
+ }
92
+
93
+ pure circuit authorizedSignerDescriptorHash(
94
+ descriptor: AuthorizedSignerDescriptor
95
+ ): Bytes<32> {
96
+ return persistentHash<AuthorizedSignerDescriptor>(descriptor);
97
+ }
98
+
99
+ export pure circuit issuerScopeCommitment(schema: SchemaRef): Bytes<32> {
100
+ assertValidSchemaRef(schema);
101
+ return persistentHash<SchemaRef>(schema);
102
+ }
103
+
104
+ export pure circuit assertProofSignerMatchesAuthorization(
105
+ proof: Proof,
106
+ descriptor: AuthorizedSignerDescriptor
107
+ ): [] {
108
+ assertValidAuthorizedSignerDescriptor(descriptor);
109
+ assert(
110
+ descriptor.state == AuthorizationState.active,
111
+ "Signer authorization must be active"
112
+ );
113
+ assert(
114
+ proof.signerVerificationMethodRef.controllerAddress
115
+ == descriptor.signerVerificationMethodRef.controllerAddress,
116
+ "Proof signer controller does not match authorization"
117
+ );
118
+ assert(
119
+ proof.signerVerificationMethodRef.methodId
120
+ == descriptor.signerVerificationMethodRef.methodId,
121
+ "Proof signer method does not match authorization"
122
+ );
123
+ assertMatchingJubjubPoints(
124
+ descriptor.signerPublicKey,
125
+ proof.publicKey
126
+ );
127
+ }
128
+
129
+ export pure circuit assertAuthorizedIssuerDescriptor(
130
+ schema: SchemaRef,
131
+ proof: Proof,
132
+ descriptor: AuthorizedSignerDescriptor
133
+ ): [] {
134
+ assertProofSignerMatchesAuthorization(proof, descriptor);
135
+ assert(
136
+ descriptor.role == SignerRole.issuer,
137
+ "Signer authorization role must be issuer"
138
+ );
139
+ assert(
140
+ descriptor.scopeCommitment == issuerScopeCommitment(schema),
141
+ "Issuer authorization scope does not match schema"
142
+ );
143
+ }
144
+
145
+ export pure circuit assertAuthorizedVerifierProof(
146
+ requestScopeCommitment: Bytes<32>,
147
+ proof: Proof,
148
+ descriptor: AuthorizedSignerDescriptor
149
+ ): [] {
150
+ assert(
151
+ requestScopeCommitment != pad(32, ""),
152
+ "Verifier request scope commitment must be set"
153
+ );
154
+ assertProofSignerMatchesAuthorization(proof, descriptor);
155
+ assert(
156
+ descriptor.role == SignerRole.verifier,
157
+ "Signer authorization role must be verifier"
158
+ );
159
+ assert(
160
+ descriptor.scopeCommitment == requestScopeCommitment,
161
+ "Verifier authorization scope does not match request"
162
+ );
163
+ assertValidVerifierRequestContextProof(requestScopeCommitment, proof);
164
+ }
165
+
166
+ export pure circuit assertValidSignerAuthorizationAuthority(
167
+ authority: SignerAuthorizationAuthority
168
+ ): [] {
169
+ assert(
170
+ authority.domainCommitment != pad(32, ""),
171
+ "Signer authorization authority domain must be set"
172
+ );
173
+ assertValidVerificationMethodRef(authority.verificationMethodRef);
174
+ assertUsableJubjubPoint(authority.publicKey);
175
+ }
176
+
177
+ export pure circuit signerAuthorizationDecisionRoot(
178
+ descriptor: AuthorizedSignerDescriptor,
179
+ domainCommitment: Bytes<32>
180
+ ): Bytes<32> {
181
+ assertValidAuthorizedSignerDescriptor(descriptor);
182
+ assert(
183
+ domainCommitment != pad(32, ""),
184
+ "Signer authorization authority domain must be set"
185
+ );
186
+ return persistentHash<Vector<2, Bytes<32>>>([
187
+ domainCommitment,
188
+ authorizedSignerDescriptorHash(descriptor)
189
+ ]);
190
+ }
191
+
192
+ export pure circuit assertValidSignerAuthorizationProof(
193
+ descriptor: AuthorizedSignerDescriptor,
194
+ authorizationProof: Proof,
195
+ authority: SignerAuthorizationAuthority
196
+ ): [] {
197
+ assertValidAuthorizedSignerDescriptor(descriptor);
198
+ assertValidSignerAuthorizationAuthority(authority);
199
+ assert(
200
+ authorizationProof.createdAt == descriptor.decisionSequence,
201
+ "Authorization proof sequence does not match descriptor"
202
+ );
203
+ assert(
204
+ authorizationProof.signerVerificationMethodRef.controllerAddress
205
+ == authority.verificationMethodRef.controllerAddress,
206
+ "Authorization proof controller does not match authority"
207
+ );
208
+ assert(
209
+ authorizationProof.signerVerificationMethodRef.methodId
210
+ == authority.verificationMethodRef.methodId,
211
+ "Authorization proof method does not match authority"
212
+ );
213
+ assertMatchingJubjubPoints(
214
+ authority.publicKey,
215
+ authorizationProof.publicKey
216
+ );
217
+ assertValidSignerAuthorizationContextProof(
218
+ signerAuthorizationDecisionRoot(descriptor, authority.domainCommitment),
219
+ authorizationProof
220
+ );
221
+ }
222
+
223
+ export pure circuit assertValidSignerAuthorizationUpdate(
224
+ previous: AuthorizedSignerDescriptor,
225
+ next: AuthorizedSignerDescriptor
226
+ ): [] {
227
+ assertValidAuthorizedSignerDescriptor(previous);
228
+ assertValidAuthorizedSignerDescriptor(next);
229
+ assert(
230
+ previous.authorizationId == next.authorizationId,
231
+ "Signer authorization update id mismatch"
232
+ );
233
+ assert(
234
+ next.decisionSequence > previous.decisionSequence,
235
+ "Signer authorization update sequence must increase"
236
+ );
237
+ assert(
238
+ next.didStateVersion >= previous.didStateVersion,
239
+ "Signer authorization DID state version must not decrease"
240
+ );
241
+ assert(
242
+ previous.state != AuthorizationState.revoked
243
+ || next.state == AuthorizationState.revoked,
244
+ "Revoked signer authorization must remain revoked"
245
+ );
246
+ }