@midnight-ntwrk/midnight-did-contract 0.5.0-rc1 → 0.5.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 (55) hide show
  1. package/README.md +4 -3
  2. package/dist/controller-key.d.ts +4 -1
  3. package/dist/controller-key.d.ts.map +1 -1
  4. package/dist/controller-key.js +3 -21
  5. package/dist/controller-key.js.map +1 -1
  6. package/dist/did.compact +394 -33
  7. package/dist/managed/did/compiler/contract-info.json +1030 -16
  8. package/dist/managed/did/contract/index.d.ts +192 -32
  9. package/dist/managed/did/contract/index.js +2295 -1054
  10. package/dist/managed/did/contract/index.js.map +1 -1
  11. package/dist/managed/did/keys/deactivate.prover +0 -0
  12. package/dist/managed/did/keys/deactivate.verifier +0 -0
  13. package/dist/managed/did/keys/removeSchnorrJubjubVerificationMethod.prover +0 -0
  14. package/dist/managed/did/keys/removeSchnorrJubjubVerificationMethod.verifier +0 -0
  15. package/dist/managed/did/keys/removeService.prover +0 -0
  16. package/dist/managed/did/keys/removeService.verifier +0 -0
  17. package/dist/managed/did/keys/removeVerificationMethod.prover +0 -0
  18. package/dist/managed/did/keys/removeVerificationMethod.verifier +0 -0
  19. package/dist/managed/did/keys/rotateControllerKey.prover +0 -0
  20. package/dist/managed/did/keys/rotateControllerKey.verifier +0 -0
  21. package/dist/managed/did/keys/setAlsoKnownAs.prover +0 -0
  22. package/dist/managed/did/keys/setAlsoKnownAs.verifier +0 -0
  23. package/dist/managed/did/keys/setSchnorrJubjubVerificationMethod.prover +0 -0
  24. package/dist/managed/did/keys/setSchnorrJubjubVerificationMethod.verifier +0 -0
  25. package/dist/managed/did/keys/setService.prover +0 -0
  26. package/dist/managed/did/keys/setService.verifier +0 -0
  27. package/dist/managed/did/keys/setVerificationMethod.prover +0 -0
  28. package/dist/managed/did/keys/setVerificationMethod.verifier +0 -0
  29. package/dist/managed/did/keys/setVerificationMethodRelation.prover +0 -0
  30. package/dist/managed/did/keys/setVerificationMethodRelation.verifier +0 -0
  31. package/dist/managed/did/zkir/deactivate.bzkir +0 -0
  32. package/dist/managed/did/zkir/deactivate.zkir +185 -127
  33. package/dist/managed/did/zkir/removeSchnorrJubjubVerificationMethod.bzkir +0 -0
  34. package/dist/managed/did/zkir/removeSchnorrJubjubVerificationMethod.zkir +301 -245
  35. package/dist/managed/did/zkir/removeService.bzkir +0 -0
  36. package/dist/managed/did/zkir/removeService.zkir +183 -127
  37. package/dist/managed/did/zkir/removeVerificationMethod.bzkir +0 -0
  38. package/dist/managed/did/zkir/removeVerificationMethod.zkir +302 -246
  39. package/dist/managed/did/zkir/rotateControllerKey.bzkir +0 -0
  40. package/dist/managed/did/zkir/rotateControllerKey.zkir +184 -127
  41. package/dist/managed/did/zkir/setAlsoKnownAs.bzkir +0 -0
  42. package/dist/managed/did/zkir/setAlsoKnownAs.zkir +270 -215
  43. package/dist/managed/did/zkir/setSchnorrJubjubVerificationMethod.bzkir +0 -0
  44. package/dist/managed/did/zkir/setSchnorrJubjubVerificationMethod.zkir +300 -246
  45. package/dist/managed/did/zkir/setService.bzkir +0 -0
  46. package/dist/managed/did/zkir/setService.zkir +268 -213
  47. package/dist/managed/did/zkir/setVerificationMethod.bzkir +0 -0
  48. package/dist/managed/did/zkir/setVerificationMethod.zkir +329 -274
  49. package/dist/managed/did/zkir/setVerificationMethodRelation.bzkir +0 -0
  50. package/dist/managed/did/zkir/setVerificationMethodRelation.zkir +620 -565
  51. package/dist/witnesses.d.ts +2 -2
  52. package/dist/witnesses.d.ts.map +1 -1
  53. package/dist/witnesses.js +2 -1
  54. package/dist/witnesses.js.map +1 -1
  55. package/package.json +6 -6
package/README.md CHANGED
@@ -28,8 +28,8 @@ sequenceDiagram
28
28
  participant Circuit as setVerificationMethod
29
29
  participant Ledger
30
30
 
31
- Caller->>Circuit: VerificationMethod input + MapMutation
32
- Circuit->>Circuit: controller auth check
31
+ Caller->>Circuit: VerificationMethod input + MapMutation + controller signature
32
+ Circuit->>Circuit: verify controller signature over contract id + version + operation + args
33
33
  Circuit->>Circuit: key type/curve constraints
34
34
  Circuit->>Circuit: duplicate/non-existence checks
35
35
  Circuit->>Ledger: insert/update state
@@ -57,7 +57,8 @@ stateDiagram-v2
57
57
 
58
58
  - Contract-level checks focus on enforceable on-chain invariants.
59
59
  - Some full DID conformance checks are intentionally handled at SDK/domain layers.
60
- - Controller public keys can be derived locally with `deriveControllerPublicKey(secretKey)`, matching the contract's `persistentHash<Vector<2, Bytes<32>>>` access-control commitment.
60
+ - Controller public keys can be derived locally with `deriveControllerPublicKey(secretKey)` as Jubjub points. Controller-gated circuits verify wallet-local signatures over a domain-separated digest containing the DID contract id, current version, operation name, and operation arguments.
61
61
  - Set/update circuits use explicit `MapMutation` and `SetMutation` enums so the exported circuit surface stays small without boolean intent flags.
62
62
  - Jubjub signing helpers and reusable Schnorr transcript logic live in `@midnight-ntwrk/midnight-did-jubjub-schnorr`.
63
63
  - The DID contract exposes one ledger-bound SchnorrJubjub verification circuit. It accepts a verification method id, looks up the native `JubjubPoint` stored in `schnorrJubjubVerificationMethods`, and verifies against that ledger key rather than a caller-supplied public key.
64
+ - Circuit `k`, rows, and managed artifact byte sizes are documented in `docs-site/compact/index.md`.
@@ -1,2 +1,5 @@
1
- export declare const deriveControllerPublicKey: (secretKey: Uint8Array) => Uint8Array;
1
+ import type { JubjubPoint } from "@midnight-ntwrk/compact-runtime";
2
+ import { type JubjubDigest, type JubjubSchnorrSignature } from "@midnight-ntwrk/midnight-did-jubjub-schnorr";
3
+ export declare const deriveControllerPublicKey: (secretKey: Uint8Array) => JubjubPoint;
4
+ export declare const signControllerAuthorization: (secretKey: Uint8Array, digest: JubjubDigest) => JubjubSchnorrSignature;
2
5
  //# sourceMappingURL=controller-key.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"controller-key.d.ts","sourceRoot":"","sources":["../src/controller-key.ts"],"names":[],"mappings":"AAiCA,eAAO,MAAM,yBAAyB,GACpC,WAAW,UAAU,KACpB,UAMF,CAAC"}
1
+ {"version":3,"file":"controller-key.d.ts","sourceRoot":"","sources":["../src/controller-key.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAEL,KAAK,YAAY,EACjB,KAAK,sBAAsB,EAE5B,MAAM,6CAA6C,CAAC;AAErD,eAAO,MAAM,yBAAyB,GACpC,WAAW,UAAU,KACpB,WAMF,CAAC;AAEF,eAAO,MAAM,2BAA2B,GACtC,WAAW,UAAU,EACrB,QAAQ,YAAY,KACnB,sBAAqE,CAAC"}
@@ -1,30 +1,12 @@
1
1
  // This file is part of midnightntwrk/midnight-did.
2
2
  // Copyright (C) 2025 Midnight Foundation
3
3
  // SPDX-License-Identifier: Apache-2.0
4
- import { CompactTypeBytes, CompactTypeVector, persistentHash } from "@midnight-ntwrk/compact-runtime";
5
- const bytes32 = new CompactTypeBytes(32);
6
- const controllerKeyInput = new CompactTypeVector(2, bytes32);
7
- const controllerKeyDomainLabel = "did:controller:pk";
8
- const padAscii32 = (value) => {
9
- if (value.length > 32) {
10
- throw new Error("DID controller key domain label exceeds 32 bytes");
11
- }
12
- const padded = new Uint8Array(32);
13
- for (let index = 0; index < value.length; index += 1) {
14
- const codePoint = value.charCodeAt(index);
15
- if (codePoint > 0x7f) {
16
- throw new Error("DID controller key domain label must be ASCII");
17
- }
18
- padded[index] = codePoint;
19
- }
20
- return padded;
21
- };
22
- // Mirrors the Compact `pad(32, "did:controller:pk")` controller-key domain.
23
- const controllerKeyDomain = padAscii32(controllerKeyDomainLabel);
4
+ import { deriveJubjubPublicKeyFromSeed, signJubjubDigestFromSeed } from "@midnight-ntwrk/midnight-did-jubjub-schnorr";
24
5
  export const deriveControllerPublicKey = (secretKey) => {
25
6
  if (!(secretKey instanceof Uint8Array) || secretKey.length !== 32) {
26
7
  throw new Error("DID controller secret key must be 32 bytes");
27
8
  }
28
- return persistentHash(controllerKeyInput, [controllerKeyDomain, secretKey]);
9
+ return deriveJubjubPublicKeyFromSeed(secretKey);
29
10
  };
11
+ export const signControllerAuthorization = (secretKey, digest) => signJubjubDigestFromSeed(secretKey, digest);
30
12
  //# sourceMappingURL=controller-key.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"controller-key.js","sourceRoot":"","sources":["../src/controller-key.ts"],"names":[],"mappings":"AAAA,mDAAmD;AACnD,yCAAyC;AACzC,sCAAsC;AAEtC,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,cAAc,EACf,MAAM,iCAAiC,CAAC;AAEzC,MAAM,OAAO,GAAG,IAAI,gBAAgB,CAAC,EAAE,CAAC,CAAC;AACzC,MAAM,kBAAkB,GAAG,IAAI,iBAAiB,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;AAC7D,MAAM,wBAAwB,GAAG,mBAAmB,CAAC;AAErD,MAAM,UAAU,GAAG,CAAC,KAAa,EAAc,EAAE;IAC/C,IAAI,KAAK,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;IACtE,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC;IAClC,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QACrD,MAAM,SAAS,GAAG,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QAC1C,IAAI,SAAS,GAAG,IAAI,EAAE,CAAC;YACrB,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;QACnE,CAAC;QACD,MAAM,CAAC,KAAK,CAAC,GAAG,SAAS,CAAC;IAC5B,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AAEF,4EAA4E;AAC5E,MAAM,mBAAmB,GAAG,UAAU,CAAC,wBAAwB,CAAC,CAAC;AAEjE,MAAM,CAAC,MAAM,yBAAyB,GAAG,CACvC,SAAqB,EACT,EAAE;IACd,IAAI,CAAC,CAAC,SAAS,YAAY,UAAU,CAAC,IAAI,SAAS,CAAC,MAAM,KAAK,EAAE,EAAE,CAAC;QAClE,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;IAChE,CAAC;IAED,OAAO,cAAc,CAAC,kBAAkB,EAAE,CAAC,mBAAmB,EAAE,SAAS,CAAC,CAAC,CAAC;AAC9E,CAAC,CAAC","sourcesContent":["// This file is part of midnightntwrk/midnight-did.\n// Copyright (C) 2025 Midnight Foundation\n// SPDX-License-Identifier: Apache-2.0\n\nimport {\n CompactTypeBytes,\n CompactTypeVector,\n persistentHash\n} from \"@midnight-ntwrk/compact-runtime\";\n\nconst bytes32 = new CompactTypeBytes(32);\nconst controllerKeyInput = new CompactTypeVector(2, bytes32);\nconst controllerKeyDomainLabel = \"did:controller:pk\";\n\nconst padAscii32 = (value: string): Uint8Array => {\n if (value.length > 32) {\n throw new Error(\"DID controller key domain label exceeds 32 bytes\");\n }\n\n const padded = new Uint8Array(32);\n for (let index = 0; index < value.length; index += 1) {\n const codePoint = value.charCodeAt(index);\n if (codePoint > 0x7f) {\n throw new Error(\"DID controller key domain label must be ASCII\");\n }\n padded[index] = codePoint;\n }\n return padded;\n};\n\n// Mirrors the Compact `pad(32, \"did:controller:pk\")` controller-key domain.\nconst controllerKeyDomain = padAscii32(controllerKeyDomainLabel);\n\nexport const deriveControllerPublicKey = (\n secretKey: Uint8Array\n): Uint8Array => {\n if (!(secretKey instanceof Uint8Array) || secretKey.length !== 32) {\n throw new Error(\"DID controller secret key must be 32 bytes\");\n }\n\n return persistentHash(controllerKeyInput, [controllerKeyDomain, secretKey]);\n};\n"]}
1
+ {"version":3,"file":"controller-key.js","sourceRoot":"","sources":["../src/controller-key.ts"],"names":[],"mappings":"AAAA,mDAAmD;AACnD,yCAAyC;AACzC,sCAAsC;AAGtC,OAAO,EACL,6BAA6B,EAG7B,wBAAwB,EACzB,MAAM,6CAA6C,CAAC;AAErD,MAAM,CAAC,MAAM,yBAAyB,GAAG,CACvC,SAAqB,EACR,EAAE;IACf,IAAI,CAAC,CAAC,SAAS,YAAY,UAAU,CAAC,IAAI,SAAS,CAAC,MAAM,KAAK,EAAE,EAAE,CAAC;QAClE,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;IAChE,CAAC;IAED,OAAO,6BAA6B,CAAC,SAAS,CAAC,CAAC;AAClD,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,2BAA2B,GAAG,CACzC,SAAqB,EACrB,MAAoB,EACI,EAAE,CAAC,wBAAwB,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC","sourcesContent":["// This file is part of midnightntwrk/midnight-did.\n// Copyright (C) 2025 Midnight Foundation\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { JubjubPoint } from \"@midnight-ntwrk/compact-runtime\";\nimport {\n deriveJubjubPublicKeyFromSeed,\n type JubjubDigest,\n type JubjubSchnorrSignature,\n signJubjubDigestFromSeed\n} from \"@midnight-ntwrk/midnight-did-jubjub-schnorr\";\n\nexport const deriveControllerPublicKey = (\n secretKey: Uint8Array\n): JubjubPoint => {\n if (!(secretKey instanceof Uint8Array) || secretKey.length !== 32) {\n throw new Error(\"DID controller secret key must be 32 bytes\");\n }\n\n return deriveJubjubPublicKeyFromSeed(secretKey);\n};\n\nexport const signControllerAuthorization = (\n secretKey: Uint8Array,\n digest: JubjubDigest\n): JubjubSchnorrSignature => signJubjubDigestFromSeed(secretKey, digest);\n"]}
package/dist/did.compact CHANGED
@@ -22,7 +22,7 @@ export { Schnorr_SchnorrSignature };
22
22
 
23
23
  // Ledger state - Full DID Document
24
24
  export ledger contractVersion: Uint<32>;
25
- export ledger controllerPublicKey: Bytes<32>;
25
+ export ledger controllerPublicKey: JubjubPoint;
26
26
  export ledger id: ContractAddress;
27
27
  export ledger alsoKnownAs: Set<Opaque<"string">>;
28
28
  export ledger version: Counter;
@@ -41,7 +41,7 @@ export ledger capabilityDelegationRelation: Set<Opaque<"string">>;
41
41
  export ledger services: Map<Opaque<"string">, Service>;
42
42
 
43
43
  // Witnesses
44
- witness localSecretKey(): Bytes<32>;
44
+ witness localControllerPublicKey(): JubjubPoint;
45
45
  witness currentTimestamp(): Uint<64>;
46
46
 
47
47
  // Enums and Structs
@@ -107,16 +107,282 @@ circuit verificationMethodExists(id: Opaque<"string">): Boolean {
107
107
  return verificationMethods.member(id) || schnorrJubjubVerificationMethods.member(id);
108
108
  }
109
109
 
110
- circuit controllerKey(sk: Bytes<32>): Bytes<32> {
111
- return persistentHash<Vector<2, Bytes<32>>>([pad(32, "did:controller:pk"), sk]);
110
+ struct ControllerAuthorizationDomain {
111
+ domain: Bytes<32>,
112
112
  }
113
113
 
114
- circuit assertController(): [] {
115
- assert(controllerKey(localSecretKey()) == controllerPublicKey, "DID controller is allowed to update the DID only");
114
+ struct ControllerAuthorizationState {
115
+ contractId: ContractAddress,
116
+ version: Uint<64>,
116
117
  }
117
118
 
118
- circuit assertControllerCanUpdate(): [] {
119
- assertController();
119
+ struct ControllerAuthorizationOperation {
120
+ name: Bytes<32>,
121
+ }
122
+
123
+ struct ControllerAuthorizationNoArgs {
124
+ domain: Bytes<32>,
125
+ }
126
+
127
+ struct RotateControllerKeyArgs {
128
+ publicKeyX: Field,
129
+ publicKeyY: Field,
130
+ }
131
+
132
+ struct SetAlsoKnownAsArgs {
133
+ value: Opaque<"string">,
134
+ mutation: SetMutation,
135
+ }
136
+
137
+ struct SetVerificationMethodArgs {
138
+ verificationMethod: VerificationMethod,
139
+ mutation: MapMutation,
140
+ }
141
+
142
+ struct RemoveVerificationMethodArgs {
143
+ id: Opaque<"string">,
144
+ }
145
+
146
+ struct SetSchnorrJubjubVerificationMethodArgs {
147
+ id: Opaque<"string">,
148
+ publicKeyX: Field,
149
+ publicKeyY: Field,
150
+ mutation: MapMutation,
151
+ }
152
+
153
+ struct RemoveSchnorrJubjubVerificationMethodArgs {
154
+ id: Opaque<"string">,
155
+ }
156
+
157
+ struct SetVerificationMethodRelationArgs {
158
+ relation: VerificationMethodRelation,
159
+ methodId: Opaque<"string">,
160
+ mutation: SetMutation,
161
+ }
162
+
163
+ struct SetServiceArgs {
164
+ service: Service,
165
+ mutation: MapMutation,
166
+ }
167
+
168
+ struct RemoveServiceArgs {
169
+ id: Opaque<"string">,
170
+ }
171
+
172
+ circuit controllerOperationHash(name: Bytes<32>): Field {
173
+ return transientHash<ControllerAuthorizationOperation>(
174
+ ControllerAuthorizationOperation { name: name }
175
+ );
176
+ }
177
+
178
+ circuit controllerNoArgsHash(): Field {
179
+ return transientHash<ControllerAuthorizationNoArgs>(
180
+ ControllerAuthorizationNoArgs { domain: pad(32, "no-args") }
181
+ );
182
+ }
183
+
184
+ export pure circuit controllerAuthorizationDigest(
185
+ contractId: ContractAddress,
186
+ expectedVersion: Uint<64>,
187
+ operationHash: Field,
188
+ argsHash: Field
189
+ ): Vector<4, Field> {
190
+ return [
191
+ transientHash<ControllerAuthorizationDomain>(
192
+ ControllerAuthorizationDomain { domain: pad(32, "midnight-did-ctrl-sig:v1") }
193
+ ),
194
+ transientHash<ControllerAuthorizationState>(
195
+ ControllerAuthorizationState {
196
+ contractId: contractId,
197
+ version: expectedVersion,
198
+ }
199
+ ),
200
+ operationHash,
201
+ argsHash,
202
+ ];
203
+ }
204
+
205
+ export pure circuit rotateControllerKeyAuthorizationDigest(
206
+ contractId: ContractAddress,
207
+ expectedVersion: Uint<64>,
208
+ newControllerPublicKey: JubjubPoint
209
+ ): Vector<4, Field> {
210
+ return controllerAuthorizationDigest(
211
+ contractId,
212
+ expectedVersion,
213
+ controllerOperationHash(pad(32, "rotateControllerKey")),
214
+ transientHash<RotateControllerKeyArgs>(
215
+ RotateControllerKeyArgs {
216
+ publicKeyX: jubjubPointX(newControllerPublicKey),
217
+ publicKeyY: jubjubPointY(newControllerPublicKey),
218
+ }
219
+ )
220
+ );
221
+ }
222
+
223
+ export pure circuit setAlsoKnownAsAuthorizationDigest(
224
+ contractId: ContractAddress,
225
+ expectedVersion: Uint<64>,
226
+ value: Opaque<"string">,
227
+ mutation: SetMutation
228
+ ): Vector<4, Field> {
229
+ return controllerAuthorizationDigest(
230
+ contractId,
231
+ expectedVersion,
232
+ controllerOperationHash(pad(32, "setAlsoKnownAs")),
233
+ transientHash<SetAlsoKnownAsArgs>(
234
+ SetAlsoKnownAsArgs { value: value, mutation: mutation }
235
+ )
236
+ );
237
+ }
238
+
239
+ export pure circuit setVerificationMethodAuthorizationDigest(
240
+ contractId: ContractAddress,
241
+ expectedVersion: Uint<64>,
242
+ verificationMethod: VerificationMethod,
243
+ mutation: MapMutation
244
+ ): Vector<4, Field> {
245
+ return controllerAuthorizationDigest(
246
+ contractId,
247
+ expectedVersion,
248
+ controllerOperationHash(pad(32, "setVerificationMethod")),
249
+ transientHash<SetVerificationMethodArgs>(
250
+ SetVerificationMethodArgs {
251
+ verificationMethod: verificationMethod,
252
+ mutation: mutation,
253
+ }
254
+ )
255
+ );
256
+ }
257
+
258
+ export pure circuit removeVerificationMethodAuthorizationDigest(
259
+ contractId: ContractAddress,
260
+ expectedVersion: Uint<64>,
261
+ id: Opaque<"string">
262
+ ): Vector<4, Field> {
263
+ return controllerAuthorizationDigest(
264
+ contractId,
265
+ expectedVersion,
266
+ controllerOperationHash(pad(32, "removeVerificationMethod")),
267
+ transientHash<RemoveVerificationMethodArgs>(
268
+ RemoveVerificationMethodArgs { id: id }
269
+ )
270
+ );
271
+ }
272
+
273
+ export pure circuit setSchnorrJubjubVerificationMethodAuthorizationDigest(
274
+ contractId: ContractAddress,
275
+ expectedVersion: Uint<64>,
276
+ verificationMethod: SchnorrJubjubVerificationMethod,
277
+ mutation: MapMutation
278
+ ): Vector<4, Field> {
279
+ return controllerAuthorizationDigest(
280
+ contractId,
281
+ expectedVersion,
282
+ controllerOperationHash(pad(32, "setSchnorrJubjubVM")),
283
+ transientHash<SetSchnorrJubjubVerificationMethodArgs>(
284
+ SetSchnorrJubjubVerificationMethodArgs {
285
+ id: verificationMethod.id,
286
+ publicKeyX: jubjubPointX(verificationMethod.publicKey),
287
+ publicKeyY: jubjubPointY(verificationMethod.publicKey),
288
+ mutation: mutation,
289
+ }
290
+ )
291
+ );
292
+ }
293
+
294
+ export pure circuit removeSchnorrJubjubVerificationMethodAuthorizationDigest(
295
+ contractId: ContractAddress,
296
+ expectedVersion: Uint<64>,
297
+ id: Opaque<"string">
298
+ ): Vector<4, Field> {
299
+ return controllerAuthorizationDigest(
300
+ contractId,
301
+ expectedVersion,
302
+ controllerOperationHash(pad(32, "removeSchnorrJubjubVM")),
303
+ transientHash<RemoveSchnorrJubjubVerificationMethodArgs>(
304
+ RemoveSchnorrJubjubVerificationMethodArgs { id: id }
305
+ )
306
+ );
307
+ }
308
+
309
+ export pure circuit setVerificationMethodRelationAuthorizationDigest(
310
+ contractId: ContractAddress,
311
+ expectedVersion: Uint<64>,
312
+ relation: VerificationMethodRelation,
313
+ methodId: Opaque<"string">,
314
+ mutation: SetMutation
315
+ ): Vector<4, Field> {
316
+ return controllerAuthorizationDigest(
317
+ contractId,
318
+ expectedVersion,
319
+ controllerOperationHash(pad(32, "setVMRelation")),
320
+ transientHash<SetVerificationMethodRelationArgs>(
321
+ SetVerificationMethodRelationArgs {
322
+ relation: relation,
323
+ methodId: methodId,
324
+ mutation: mutation,
325
+ }
326
+ )
327
+ );
328
+ }
329
+
330
+ export pure circuit setServiceAuthorizationDigest(
331
+ contractId: ContractAddress,
332
+ expectedVersion: Uint<64>,
333
+ service: Service,
334
+ mutation: MapMutation
335
+ ): Vector<4, Field> {
336
+ return controllerAuthorizationDigest(
337
+ contractId,
338
+ expectedVersion,
339
+ controllerOperationHash(pad(32, "setService")),
340
+ transientHash<SetServiceArgs>(
341
+ SetServiceArgs { service: service, mutation: mutation }
342
+ )
343
+ );
344
+ }
345
+
346
+ export pure circuit removeServiceAuthorizationDigest(
347
+ contractId: ContractAddress,
348
+ expectedVersion: Uint<64>,
349
+ id: Opaque<"string">
350
+ ): Vector<4, Field> {
351
+ return controllerAuthorizationDigest(
352
+ contractId,
353
+ expectedVersion,
354
+ controllerOperationHash(pad(32, "removeService")),
355
+ transientHash<RemoveServiceArgs>(RemoveServiceArgs { id: id })
356
+ );
357
+ }
358
+
359
+ export pure circuit deactivateAuthorizationDigest(
360
+ contractId: ContractAddress,
361
+ expectedVersion: Uint<64>
362
+ ): Vector<4, Field> {
363
+ return controllerAuthorizationDigest(
364
+ contractId,
365
+ expectedVersion,
366
+ controllerOperationHash(pad(32, "deactivate")),
367
+ controllerNoArgsHash()
368
+ );
369
+ }
370
+
371
+ circuit assertController(
372
+ signature: Schnorr_SchnorrSignature,
373
+ expectedVersion: Uint<64>,
374
+ digest: Vector<4, Field>
375
+ ): [] {
376
+ assert(disclose(expectedVersion) == version, "Controller authorization version is stale");
377
+ Schnorr_schnorrVerifyDigest(digest, signature, controllerPublicKey);
378
+ }
379
+
380
+ circuit assertControllerCanUpdate(
381
+ signature: Schnorr_SchnorrSignature,
382
+ expectedVersion: Uint<64>,
383
+ digest: Vector<4, Field>
384
+ ): [] {
385
+ assertController(signature, expectedVersion, digest);
120
386
  assert(active, "Contract is not active");
121
387
  }
122
388
 
@@ -211,27 +477,44 @@ constructor() {
211
477
  id = kernel.self();
212
478
  active = true;
213
479
  deactivated = false;
214
- controllerPublicKey = disclose(controllerKey(localSecretKey()));
480
+ controllerPublicKey = disclose(localControllerPublicKey());
215
481
 
216
482
  const timestamp = disclose(currentTimestamp());
217
483
  created = timestamp;
218
484
  updated = timestamp;
219
485
  }
220
486
 
221
- export circuit rotateControllerKey(newControllerPublicKey: Bytes<32>): [] {
222
- assertControllerCanUpdate();
487
+ export circuit rotateControllerKey(
488
+ newControllerPublicKey: JubjubPoint,
489
+ controllerSignature: Schnorr_SchnorrSignature,
490
+ expectedVersion: Uint<64>
491
+ ): [] {
223
492
  const disclosedNewControllerPublicKey = disclose(newControllerPublicKey);
493
+ assertControllerCanUpdate(
494
+ controllerSignature,
495
+ expectedVersion,
496
+ rotateControllerKeyAuthorizationDigest(id, disclose(expectedVersion), disclosedNewControllerPublicKey)
497
+ );
224
498
  assert(disclosedNewControllerPublicKey != controllerPublicKey, "New controller key matches current controller key");
225
499
  controllerPublicKey = disclosedNewControllerPublicKey;
226
500
 
227
501
  recordUpdate();
228
502
  }
229
503
 
230
- export circuit setAlsoKnownAs(value: Opaque<"string">, mutation: SetMutation): [] {
231
- assertControllerCanUpdate();
504
+ export circuit setAlsoKnownAs(
505
+ value: Opaque<"string">,
506
+ mutation: SetMutation,
507
+ controllerSignature: Schnorr_SchnorrSignature,
508
+ expectedVersion: Uint<64>
509
+ ): [] {
232
510
  const disclosedMutation = disclose(mutation);
233
- assertSetMutationDefined(disclosedMutation);
234
511
  const alias = disclose(value);
512
+ assertControllerCanUpdate(
513
+ controllerSignature,
514
+ expectedVersion,
515
+ setAlsoKnownAsAuthorizationDigest(id, disclose(expectedVersion), alias, disclosedMutation)
516
+ );
517
+ assertSetMutationDefined(disclosedMutation);
235
518
  if (disclosedMutation == SetMutation.Insert) {
236
519
  assert(!alsoKnownAs.member(alias), "alsoKnownAs value already exists");
237
520
  alsoKnownAs.insert(alias);
@@ -245,11 +528,22 @@ export circuit setAlsoKnownAs(value: Opaque<"string">, mutation: SetMutation): [
245
528
 
246
529
  export circuit setVerificationMethod(
247
530
  verificationMethod: VerificationMethod,
248
- mutation: MapMutation
531
+ mutation: MapMutation,
532
+ controllerSignature: Schnorr_SchnorrSignature,
533
+ expectedVersion: Uint<64>
249
534
  ): [] {
250
- assertControllerCanUpdate();
251
535
  const disclosedVerificationMethod = disclose(verificationMethod);
252
536
  const disclosedMutation = disclose(mutation);
537
+ assertControllerCanUpdate(
538
+ controllerSignature,
539
+ expectedVersion,
540
+ setVerificationMethodAuthorizationDigest(
541
+ id,
542
+ disclose(expectedVersion),
543
+ disclosedVerificationMethod,
544
+ disclosedMutation
545
+ )
546
+ );
253
547
  assertMapMutationDefined(disclosedMutation);
254
548
  assertSupportedVerificationMethod(disclosedVerificationMethod);
255
549
  if (disclosedMutation == MapMutation.Update) {
@@ -263,9 +557,17 @@ export circuit setVerificationMethod(
263
557
  recordUpdate();
264
558
  }
265
559
 
266
- export circuit removeVerificationMethod(id: Opaque<"string">): [] {
267
- assertControllerCanUpdate();
268
- const disclosedId = disclose(id);
560
+ export circuit removeVerificationMethod(
561
+ methodId: Opaque<"string">,
562
+ controllerSignature: Schnorr_SchnorrSignature,
563
+ expectedVersion: Uint<64>
564
+ ): [] {
565
+ const disclosedId = disclose(methodId);
566
+ assertControllerCanUpdate(
567
+ controllerSignature,
568
+ expectedVersion,
569
+ removeVerificationMethodAuthorizationDigest(id, disclose(expectedVersion), disclosedId)
570
+ );
269
571
  assert(verificationMethods.member(disclosedId), "Verification method does not exist");
270
572
  assertVerificationMethodIsNotReferenced(disclosedId);
271
573
  verificationMethods.remove(disclosedId);
@@ -275,11 +577,22 @@ export circuit removeVerificationMethod(id: Opaque<"string">): [] {
275
577
 
276
578
  export circuit setSchnorrJubjubVerificationMethod(
277
579
  verificationMethod: SchnorrJubjubVerificationMethod,
278
- mutation: MapMutation
580
+ mutation: MapMutation,
581
+ controllerSignature: Schnorr_SchnorrSignature,
582
+ expectedVersion: Uint<64>
279
583
  ): [] {
280
- assertControllerCanUpdate();
281
584
  const disclosedVerificationMethod = disclose(verificationMethod);
282
585
  const disclosedMutation = disclose(mutation);
586
+ assertControllerCanUpdate(
587
+ controllerSignature,
588
+ expectedVersion,
589
+ setSchnorrJubjubVerificationMethodAuthorizationDigest(
590
+ id,
591
+ disclose(expectedVersion),
592
+ disclosedVerificationMethod,
593
+ disclosedMutation
594
+ )
595
+ );
283
596
  assertMapMutationDefined(disclosedMutation);
284
597
  if (disclosedMutation == MapMutation.Update) {
285
598
  assert(schnorrJubjubVerificationMethods.member(disclosedVerificationMethod.id), "Verification method does not exist");
@@ -292,9 +605,21 @@ export circuit setSchnorrJubjubVerificationMethod(
292
605
  recordUpdate();
293
606
  }
294
607
 
295
- export circuit removeSchnorrJubjubVerificationMethod(id: Opaque<"string">): [] {
296
- assertControllerCanUpdate();
297
- const disclosedId = disclose(id);
608
+ export circuit removeSchnorrJubjubVerificationMethod(
609
+ methodId: Opaque<"string">,
610
+ controllerSignature: Schnorr_SchnorrSignature,
611
+ expectedVersion: Uint<64>
612
+ ): [] {
613
+ const disclosedId = disclose(methodId);
614
+ assertControllerCanUpdate(
615
+ controllerSignature,
616
+ expectedVersion,
617
+ removeSchnorrJubjubVerificationMethodAuthorizationDigest(
618
+ id,
619
+ disclose(expectedVersion),
620
+ disclosedId
621
+ )
622
+ );
298
623
  assert(schnorrJubjubVerificationMethods.member(disclosedId), "Verification method does not exist");
299
624
  assertVerificationMethodIsNotReferenced(disclosedId);
300
625
  schnorrJubjubVerificationMethods.remove(disclosedId);
@@ -319,12 +644,24 @@ export circuit verifySchnorrJubjubDigestSignature(
319
644
  export circuit setVerificationMethodRelation(
320
645
  relation: VerificationMethodRelation,
321
646
  methodId: Opaque<"string">,
322
- mutation: SetMutation
647
+ mutation: SetMutation,
648
+ controllerSignature: Schnorr_SchnorrSignature,
649
+ expectedVersion: Uint<64>
323
650
  ): [] {
324
- assertControllerCanUpdate();
325
651
  const disclosedRelation = disclose(relation);
326
652
  const disclosedMethodId = disclose(methodId);
327
653
  const disclosedMutation = disclose(mutation);
654
+ assertControllerCanUpdate(
655
+ controllerSignature,
656
+ expectedVersion,
657
+ setVerificationMethodRelationAuthorizationDigest(
658
+ id,
659
+ disclose(expectedVersion),
660
+ disclosedRelation,
661
+ disclosedMethodId,
662
+ disclosedMutation
663
+ )
664
+ );
328
665
  assertSetMutationDefined(disclosedMutation);
329
666
  assert(verificationMethodExists(disclosedMethodId), "Verification method does not exist");
330
667
  assert(disclosedRelation != VerificationMethodRelation.Undefined, "Verification relation must be defined");
@@ -340,10 +677,19 @@ export circuit setVerificationMethodRelation(
340
677
  recordUpdate();
341
678
  }
342
679
 
343
- export circuit setService(service: Service, mutation: MapMutation): [] {
344
- assertControllerCanUpdate();
680
+ export circuit setService(
681
+ service: Service,
682
+ mutation: MapMutation,
683
+ controllerSignature: Schnorr_SchnorrSignature,
684
+ expectedVersion: Uint<64>
685
+ ): [] {
345
686
  const disclosedService = disclose(service);
346
687
  const disclosedMutation = disclose(mutation);
688
+ assertControllerCanUpdate(
689
+ controllerSignature,
690
+ expectedVersion,
691
+ setServiceAuthorizationDigest(id, disclose(expectedVersion), disclosedService, disclosedMutation)
692
+ );
347
693
  assertMapMutationDefined(disclosedMutation);
348
694
  if (disclosedMutation == MapMutation.Update) {
349
695
  assert(services.member(disclosedService.id), "Service with a given id does not exist");
@@ -356,17 +702,32 @@ export circuit setService(service: Service, mutation: MapMutation): [] {
356
702
  recordUpdate();
357
703
  }
358
704
 
359
- export circuit removeService(id: Opaque<"string">): [] {
360
- assertControllerCanUpdate();
361
- const disclosedId = disclose(id);
705
+ export circuit removeService(
706
+ serviceId: Opaque<"string">,
707
+ controllerSignature: Schnorr_SchnorrSignature,
708
+ expectedVersion: Uint<64>
709
+ ): [] {
710
+ const disclosedId = disclose(serviceId);
711
+ assertControllerCanUpdate(
712
+ controllerSignature,
713
+ expectedVersion,
714
+ removeServiceAuthorizationDigest(id, disclose(expectedVersion), disclosedId)
715
+ );
362
716
  assert(services.member(disclosedId), "Service with a given id does not exist");
363
717
  services.remove(disclosedId);
364
718
 
365
719
  recordUpdate();
366
720
  }
367
721
 
368
- export circuit deactivate(): [] {
369
- assertController();
722
+ export circuit deactivate(
723
+ controllerSignature: Schnorr_SchnorrSignature,
724
+ expectedVersion: Uint<64>
725
+ ): [] {
726
+ assertController(
727
+ controllerSignature,
728
+ expectedVersion,
729
+ deactivateAuthorizationDigest(id, disclose(expectedVersion))
730
+ );
370
731
  assert(active, "DID is already inactive");
371
732
  active = false;
372
733
  deactivated = true;