-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathtyronZIL.scilla
434 lines (387 loc) · 17.7 KB
/
tyronZIL.scilla
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
(* v3.7.0
tyronZIL: W3C Decentralized Identifier (DID) DApp
Self-Sovereign Identity Protocol
Copyright Tyron Mapu Community Interest Company 2023. All rights reserved.
You acknowledge and agree that Tyron Mapu Community Interest Company (Tyron) own all legal right, title and interest in and to the work, software, application, source code, documentation and any other documents in this repository (collectively, the Program), including any intellectual property rights which subsist in the Program (whether those rights happen to be registered or not, and wherever in the world those rights may exist), whether in source code or any other form.
Subject to the limited license below, you may not (and you may not permit anyone else to) distribute, publish, copy, modify, merge, combine with another program, create derivative works of, reverse engineer, decompile or otherwise attempt to extract the source code of, the Program or any part thereof, except that you may contribute to this repository.
You are granted a non-exclusive, non-transferable, non-sublicensable license to distribute, publish, copy, modify, merge, combine with another program or create derivative works of the Program (such resulting program, collectively, the Resulting Program) solely for Non-Commercial Use as long as you:
1. give prominent notice (Notice) with each copy of the Resulting Program that the Program is used in the Resulting Program and that the Program is the copyright of Tyron; and
2. subject the Resulting Program and any distribution, publication, copy, modification, merger therewith, combination with another program or derivative works thereof to the same Notice requirement and Non-Commercial Use restriction set forth herein.
Non-Commercial Use means each use as described in clauses (1)-(3) below, as reasonably determined by Tyron in its sole discretion:
1. personal use for research, personal study, private entertainment, hobby projects or amateur pursuits, in each case without any anticipated commercial application;
2. use by any charitable organization, educational institution, public research organization, public safety or health organization, environmental protection organization or government institution; or
3. the number of monthly active users of the Resulting Program across all versions thereof and platforms globally do not exceed 10,000 at any time.
You will not use any trade mark, service mark, trade name, logo of Tyron or any other company or organization in a way that is likely or intended to cause confusion about the owner or authorized user of such marks, names or logos.
If you have any questions, comments or interest in pursuing any other use cases, please reach out to us at [email protected].*)
scilla_version 0
import BoolUtils
library DID
let tyronAddr = 0xA3725fA67FaA3a1cAe6869C57b475ff173D98Ba7
type DidStatus =
| Deployed
| Created
| Recovered
| Updated
| Deactivated
type Operation =
| Recovery
| Update
type Action =
| Add
| Remove
type TransferProtocol =
| Https
| Git
type BlockchainType =
| Zilliqa of ByStr20
| Other of String
type Endpoint =
| Address of BlockchainType
| Uri of String TransferProtocol String (* type, transfer protocol & uri *)
type Document =
| VerificationMethod of Action String ByStr33 String (* add/remove, key purpose, public key & encrypted private key *)
| Service of Action String Endpoint (* add/remove, service ID & service *)
let didRecovery = Recovery
let didUpdate = Update
let update = "update"
let recovery = "recovery"
let actionAdd = "add"
let actionRemove = "remove"
let empty_methods = Emp String ByStr33
let empty_dkms = Emp String String
let empty_services = Emp String ByStr20
let empty_services_ = Emp String Endpoint
let one_msg = fun( msg: Message ) =>
let nil_msg = Nil{ Message } in Cons{ Message } msg nil_msg
type Error =
| CodeWrongStatus
| CodeWrongCaller
| CodeWrongSignature
| CodeUndefinedKey
| CodeSameKey
| CodeSameId
| CodeNotValid
| CodeDidLocked
| CodeSameAddress
let make_error = fun( error: Error ) =>
let result = match error with
| CodeWrongStatus => Int32 -1
| CodeWrongCaller => Int32 -2
| CodeWrongSignature => Int32 -3
| CodeUndefinedKey => Int32 -4
| CodeSameKey => Int32 -5
| CodeSameId => Int32 -6
| CodeNotValid => Int32 -7
| CodeDidLocked => Int32 -8
| CodeSameAddress => Int32 -9
end in { _exception: "Error"; code: result }
let zero = Uint128 0
let zeroByStr20 = 0x0000000000000000000000000000000000000000
let zeroByStr33 = 0x000000000000000000000000000000000000000000000000000000000000000000
let zeroByStr64 = 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
let zeroByStr = builtin to_bystr zeroByStr20
let option_value = tfun 'A => fun( default: 'A ) => fun( input: Option 'A) =>
match input with
| Some v => v
| None => default end
let option_uint128_value = let f = @option_value Uint128 in f zero
let option_bystr20_value = let f = @option_value ByStr20 in f zeroByStr20
let option_bystr33_value = let f = @option_value ByStr33 in f zeroByStr33
let option_bystr64_value = let f = @option_value ByStr64 in f zeroByStr64
contract DID( init_controller: ByStr20 )
field did: String = "" (* the W3C decentralized identifier *)
field nft_username: String = ""
field controller: ByStr20 = init_controller
field pending_controller: ByStr20 = zeroByStr20
field did_status: DidStatus = Deployed
field version: String = "tyronZIL__3.7.0" (* @todo update *)
(* Verification methods @key: key purpose @value: public key of type "SchnorrSecp256k1VerificationKey2019" *)
field verification_methods: Map String ByStr33 = empty_methods
(* Decentralized Key Management System *)
field dkms: Map String String = empty_dkms
(* Services @key: ID @value: endpoint *)
field services: Map String ByStr20 = empty_services
field services_: Map String Endpoint = empty_services_
field did_hash: ByStr = zeroByStr
(* The block number when the DID Create operation occurred *)
field did_created: BNum = BNum 0
(* The block number when the last DID CRUD operation occurred *)
field ledger_time: BNum = BNum 0
(* A monotonically increasing number representing the amount of transactions that have taken place *)
field tx_number: Uint128 = zero
field did_domain_dns: Map String ByStr20 = Emp String ByStr20
procedure SupportTyron( tyron: Option Uint128 )
match tyron with
| Some donation =>
accept; msg = let m = { _tag: ""; _recipient: tyronAddr; _amount: donation } in one_msg m; send msg
| None => end end
procedure ThrowError( err: Error )
e = make_error err; throw e end
procedure IsOperational()
current_status <- did_status;
match current_status with
| Deactivated => err = CodeWrongStatus; ThrowError err
| _ => end end
procedure VerifyController( tyron: Option Uint128 )
current_controller <- controller;
verified = builtin eq _origin current_controller; match verified with
| True => SupportTyron tyron
| False => err = CodeWrongCaller; ThrowError err end end
procedure Timestamp()
current_block <- &BLOCKNUMBER; latest_tx_number <- tx_number; ledger_time := current_block;
new_tx_number = let incrementor = Uint128 1 in builtin add latest_tx_number incrementor; tx_number := new_tx_number end
procedure ThrowIfSameAddr(
a: ByStr20,
b: ByStr20
)
is_self = builtin eq a b; match is_self with
| False => | True => err = CodeSameAddress; ThrowError err end end
transition UpdateController(
addr: ByStr20,
tyron: Option Uint128
)
IsOperational; VerifyController tyron;
current_controller <- controller; ThrowIfSameAddr current_controller addr;
pending_controller := addr; Timestamp end
transition AcceptPendingController()
IsOperational; current_pending <- pending_controller;
verified = builtin eq _origin current_pending; match verified with
| True => | False => err = CodeWrongCaller; ThrowError err end;
controller := current_pending end
(* Verify Schnorr signature - signed data must correspond with a DID key *)
procedure VerifySignature(
id: String,
signedData: ByStr,
signature: ByStr64
)
get_did_key <- verification_methods[id]; did_key = option_bystr33_value get_did_key;
is_right_signature = builtin schnorr_verify did_key signedData signature; match is_right_signature with
| True =>
| False => err = CodeWrongSignature; ThrowError err end end
procedure ThrowIfNoKey( optKey: Option ByStr33 )
match optKey with
| Some key =>
| None => err = CodeUndefinedKey; ThrowError err end end
procedure ThrowIfSameKey(
key: ByStr33,
sndKey: ByStr33
)
is_same_key = builtin eq key sndKey; match is_same_key with
| True => err = CodeSameKey; ThrowError err
| False => end end
procedure VerifyDIDkeys(
operation: Operation,
didRecovery: ByStr33,
didUpdate: ByStr33
)
get_update_key <- verification_methods[update]; new_update = option_bystr33_value get_update_key;
match operation with
| Recovery =>
get_recovery_key <- verification_methods[recovery]; new_recovery = option_bystr33_value get_recovery_key;
ThrowIfSameKey new_recovery new_update;
ThrowIfSameKey new_recovery didRecovery; ThrowIfSameKey new_recovery didUpdate; ThrowIfSameKey new_update didRecovery; ThrowIfSameKey new_update didUpdate
| Update => ThrowIfSameKey new_update didUpdate; ThrowIfSameKey new_update didRecovery end end
procedure SaveDocument( document: Document )
match document with
| VerificationMethod action purpose key encrypted =>
key_exists <- exists verification_methods[purpose];
match action with
| Add =>
match key_exists with
| True => err = CodeSameId; ThrowError err
| False =>
verification_methods[purpose] := key;
dkms[purpose] := encrypted end
| Remove => err = CodeNotValid; ThrowError err end
| Service action id endpoint =>
is_service <- exists services[id];
is_service_ <- exists services_[id];
service_exists = orb is_service is_service_;
match action with
| Add =>
match service_exists with
| True => err = CodeSameId; ThrowError err
| False =>
match endpoint with
| Address address =>
match address with
| Zilliqa addr => services[id] := addr
| Other adrr => services_[id] := endpoint end
| Uri eType protocol uri => services_[id] := endpoint end end
| Remove => err = CodeNotValid; ThrowError err end end end
transition DidCreate(
document: List Document,
signature: Option ByStr64,
tyron: Option Uint128
)
current_status <- did_status;
match current_status with
| Deployed =>
VerifyController tyron;
new_did = let did_prefix = "did:tyron:zil:main:" in let did_suffix = builtin to_string _this_address in
builtin concat did_prefix did_suffix; did := new_did;
forall document SaveDocument;
get_recovery_key <- verification_methods[recovery]; ThrowIfNoKey get_recovery_key; did_recovery = option_bystr33_value get_recovery_key;
get_update_key <- verification_methods[update]; ThrowIfNoKey get_update_key; did_update = option_bystr33_value get_update_key;
ThrowIfSameKey did_recovery did_update;
new_status = Created; did_status := new_status;
current_block <- &BLOCKNUMBER; did_created := current_block; Timestamp
| _ => err = CodeWrongStatus; ThrowError err end end
procedure UpdateDocument( document: Document )
match document with
| VerificationMethod action purpose key encrypted =>
match action with
| Add =>
verification_methods[purpose] := key;
dkms[purpose] := encrypted
| Remove =>
key_exists <- exists verification_methods[purpose];
match key_exists with
| True =>
delete verification_methods[purpose];
delete dkms[purpose]
| False => err = CodeNotValid; ThrowError err end end
| Service action id endpoint =>
match action with
| Add =>
match endpoint with
| Address address =>
match address with
| Zilliqa addr => services[id] := addr
| Other adrr => services_[id] := endpoint end
| Uri eType protocol uri => services_[id] := endpoint end
| Remove =>
is_service <- exists services[id];
is_service_ <- exists services_[id];
service_exists = orb is_service is_service_;
match service_exists with
| True => delete services[id]; delete services_[id]
| False => err = CodeNotValid; ThrowError err end end end end
procedure ValidateDocument(
operation: Operation,
document: List Document
)
match operation with
| Recovery =>
verification_methods := empty_methods; dkms := empty_dkms; services := empty_services; services_ := empty_services_;
forall document SaveDocument
| Update => forall document UpdateDocument end end
procedure HashDocument( document: Document )
doc_hash <- did_hash;
element_hash = match document with
| VerificationMethod action purpose key encrypted =>
match action with
| Add =>
let h1 = builtin sha256hash actionAdd in
let h2 = builtin sha256hash purpose in
let h3 = builtin sha256hash key in
let h4 = builtin sha256hash encrypted in
let h1_2 = builtin concat h1 h2 in
let h1_3 = builtin concat h1_2 h3 in
let hash = builtin concat h1_3 h4 in
builtin to_bystr hash
| Remove =>
let h1 = builtin sha256hash actionRemove in
let h2 = builtin sha256hash purpose in
let hash = builtin concat h1 h2 in
builtin to_bystr hash end
| Service action id endpoint =>
match action with
| Add =>
let h1 = builtin sha256hash actionAdd in
let h2 = builtin sha256hash id in
match endpoint with
| Uri eType transfer uri =>
let h3 = builtin sha256hash uri in
let h1_2 = builtin concat h1 h2 in
let hash = builtin concat h1_2 h3 in
builtin to_bystr hash
| Address address =>
match address with
| Zilliqa addr =>
let h3 = builtin sha256hash addr in
let h1_2 = builtin concat h1 h2 in
let hash = builtin concat h1_2 h3 in
builtin to_bystr hash
| Other addr =>
let h3 = builtin sha256hash addr in
let h1_2 = builtin concat h1 h2 in
let hash = builtin concat h1_2 h3 in
builtin to_bystr hash end end
| Remove =>
let h1 = builtin sha256hash actionRemove in
let h2 = builtin sha256hash id in
let hash = builtin concat h1 h2 in
builtin to_bystr hash end end;
new_doc_hash = builtin concat doc_hash element_hash;
did_hash := new_doc_hash end
procedure VerifyDocument(
operation: Operation,
document: List Document,
signature: Option ByStr64
)
did_hash := zeroByStr;
forall document HashDocument;
doc_hash <- did_hash;
sig = option_bystr64_value signature;
id = match operation with
| Recovery => recovery
| Update => update end;
VerifySignature id doc_hash sig;
ValidateDocument operation document end
transition DidRecover(
document: List Document,
signature: Option ByStr64,
tyron: Option Uint128
)
current_status <- did_status;
match current_status with
| Created => | Recovered => | Updated =>
| _ => err = CodeWrongStatus; ThrowError err end;
VerifyController tyron;
get_recovery_key <- verification_methods[recovery]; did_recovery = option_bystr33_value get_recovery_key;
get_update_key <- verification_methods[update]; did_update = option_bystr33_value get_update_key;
VerifyDocument didRecovery document signature;
VerifyDIDkeys didRecovery did_recovery did_update;
new_status = Recovered; did_status := new_status; Timestamp end
transition DidUpdate(
document: List Document,
signature: Option ByStr64,
tyron: Option Uint128
)
current_status <- did_status;
match current_status with
| Created => | Recovered => | Updated =>
| _ => err = CodeWrongStatus; ThrowError err end;
VerifyController tyron;
get_recovery_key <- verification_methods[recovery]; did_recovery = option_bystr33_value get_recovery_key;
get_update_key <- verification_methods[update]; did_update = option_bystr33_value get_update_key;
VerifyDocument didUpdate document signature;
VerifyDIDkeys didUpdate did_recovery did_update;
new_status = Updated; did_status := new_status; Timestamp end
transition DidDeactivate(
document: List Document,
signature: Option ByStr64,
tyron: Option Uint128
)
current_status <- did_status;
match current_status with
| Created => | Recovered => | Updated =>
| _ => err = CodeWrongStatus; ThrowError err end;
VerifyController tyron;
VerifyDocument didRecovery document signature;
verification_methods := empty_methods; services := empty_services; services_ := empty_services_;
new_status = Deactivated; did_status := new_status; Timestamp end
transition Dns(
addr: ByStr20,
domain: String,
didKey: ByStr33,
encrypted: String,
tyron: Option Uint128
)
current_status <- did_status; match current_status with
| Created => | Recovered => | Updated =>
| _ => err = CodeWrongStatus; ThrowError err end;
VerifyController tyron; ThrowIfSameAddr _this_address addr;
verification_methods[domain] := didKey; dkms[domain] := encrypted; did_domain_dns[domain] := addr;
new_status = Updated; did_status := new_status; Timestamp end