vchain_client 1.0.15 → 1.0.16
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.
- checksums.yaml +4 -4
- data/lib/vchain_client.rb +804 -737
- data/lib/vchain_client/bitcoind_blockchain_adapter.rb +16 -2
- data/lib/vchain_client/blockstack_client.rb +4 -0
- data/lib/vchain_client/signatures.rb +73 -51
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d4d647625f6cb2ba6bd8783a3da98bd8a0845cb6
|
4
|
+
data.tar.gz: dcf9699f8907e8a5fdb3cfe73f62ef9f8a50a439
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4ff4a4f2ebeccf0d056eaa9b8aae892716d179b19e3c28c793c1da5f9dbad4741abdd3923fbcb1afdcb0d93ca6b29675fdb3d4ae648c545f7ef51fd0c0e3d932
|
7
|
+
data.tar.gz: ca812c1e1f01704802606a27a7b8cf2e6996f8cacc4f9de9b86a442b41a5284cd716cffa2fb6958c8ace666bd43659df6e2f1445609e8468ae0e2c521d07a921
|
data/lib/vchain_client.rb
CHANGED
@@ -15,7 +15,11 @@ module VChainClient
|
|
15
15
|
require 'vchain_client/signatures'
|
16
16
|
require 'vchain_client/blockstack_client'
|
17
17
|
|
18
|
-
|
18
|
+
FIELD_TYPE_TRAVEL_DOCUMENT = "travel_document"
|
19
|
+
FIELD_TYPE_TEST_DOCUMENT = "test_document"
|
20
|
+
|
21
|
+
FIELD_TYPE_TRAVEL_DOCUMENT_HASHED = "fbb6889f44061c2a91e17a411cf168f9457981257a5e0a31fb706cd5cd1e64c263780a42a1fd858ee69429869ab2e2c53b9d94c4a26946f2b0c12f8ce2812d6b"
|
22
|
+
FIELD_TYPE_TEST_DOCUMENT_HASHED = "e061cf61078d74025ab1d136e0a78785097b8ef721107e940cac1ca836ed5fa6af907344b761447274ce0558d95d4126e94e11f04eb70c3885afcc96f9cfe985"
|
19
23
|
|
20
24
|
@config = nil
|
21
25
|
@log = nil
|
@@ -32,23 +36,94 @@ module VChainClient
|
|
32
36
|
}
|
33
37
|
end
|
34
38
|
|
39
|
+
def full_hash(arr)
|
40
|
+
output = {}
|
41
|
+
|
42
|
+
arr.each { |k, v|
|
43
|
+
if k != "doc_hash"
|
44
|
+
output[Digest::SHA512.hexdigest(k)] = Digest::SHA512.hexdigest(v)
|
45
|
+
else
|
46
|
+
output[k] = Digest::SHA512.hexdigest(v)
|
47
|
+
end
|
48
|
+
}
|
49
|
+
|
50
|
+
return output
|
51
|
+
end
|
52
|
+
|
35
53
|
def cut(arr)
|
36
54
|
arr.each { |k, v|
|
37
|
-
if
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
55
|
+
if arr["type"] == FIELD_TYPE_TRAVEL_DOCUMENT_HASHED
|
56
|
+
if k == "type" || k == "citizenship" || k == "first_name" || k == "last_name" || k == "birthdate" || k == "number" || k == "sex"
|
57
|
+
arr[k] = v
|
58
|
+
else
|
59
|
+
arr.delete(k)
|
60
|
+
end
|
42
61
|
|
43
|
-
|
62
|
+
elsif arr["type"] == FIELD_TYPE_TEST_DOCUMENT_HASHED
|
63
|
+
if k == "type" || k == "a" || k == "b" || k == "c" || k == "d" || k == "e"
|
64
|
+
arr[k] = v
|
65
|
+
else
|
66
|
+
arr.delete(k)
|
67
|
+
end
|
44
68
|
|
45
69
|
end
|
46
70
|
}
|
47
71
|
end
|
48
72
|
|
73
|
+
def get_doc_hash(arr)
|
74
|
+
if arr["type"] == FIELD_TYPE_TRAVEL_DOCUMENT_HASHED
|
75
|
+
|
76
|
+
what_to_hash = arr["type"] + arr["citizenship"] + arr["number"] + arr["first_name"] + arr["last_name"] + arr["birthdate"] + arr["sex"]
|
77
|
+
|
78
|
+
return Digest::SHA512.hexdigest(what_to_hash)
|
79
|
+
|
80
|
+
elsif arr["type"] == FIELD_TYPE_TEST_DOCUMENT_HASHED
|
81
|
+
|
82
|
+
what_to_hash = arr["type"] + arr["a"] + arr["b"] + arr["c"] + arr["d"] + arr["e"]
|
83
|
+
|
84
|
+
return Digest::SHA512.hexdigest(what_to_hash)
|
85
|
+
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
49
89
|
def get_credentials_fields(type)
|
50
|
-
if type ==
|
90
|
+
if type == FIELD_TYPE_TRAVEL_DOCUMENT_HASHED
|
51
91
|
return ["type", "citizenship", "number", "first_name", "last_name", "birthdate"]
|
92
|
+
|
93
|
+
elsif type == FIELD_TYPE_TEST_DOCUMENT_HASHED
|
94
|
+
return ["type", "a", "b", "c"]
|
95
|
+
|
96
|
+
end
|
97
|
+
|
98
|
+
if @log.error?
|
99
|
+
@log.error("[get_credentials_fields] unknown document type: '"+ type +"'")
|
100
|
+
end
|
101
|
+
|
102
|
+
return nil
|
103
|
+
end
|
104
|
+
|
105
|
+
def get_similar_credential_sets(type)
|
106
|
+
if type == FIELD_TYPE_TRAVEL_DOCUMENT_HASHED
|
107
|
+
output = []
|
108
|
+
output.push(["type", "last_name", "birthdate", "number", "citizenship"])
|
109
|
+
output.push(["type", "first_name", "birthdate", "number", "citizenship"])
|
110
|
+
output.push(["type", "first_name", "last_name", "birthdate", "number"])
|
111
|
+
output.push(["type", "first_name", "last_name", "birthdate", "citizenship"])
|
112
|
+
output.push(["type", "first_name", "last_name", "number", "citizenship"])
|
113
|
+
output.push(["type", "last_name", "number", "citizenship"])
|
114
|
+
output.push(["type", "first_name", "number", "citizenship"])
|
115
|
+
output.push(["type", "birthdate", "number", "citizenship"])
|
116
|
+
output.push(["type", "first_name", "last_name", "birthdate"])
|
117
|
+
output.push(["type", "number", "citizenship"])
|
118
|
+
return output
|
119
|
+
|
120
|
+
elsif type == FIELD_TYPE_TEST_DOCUMENT_HASHED
|
121
|
+
output = []
|
122
|
+
output.push(["type", "a", "b"])
|
123
|
+
output.push(["type", "a", "c"])
|
124
|
+
output.push(["type", "b", "c"])
|
125
|
+
return output
|
126
|
+
|
52
127
|
end
|
53
128
|
|
54
129
|
if @log.error?
|
@@ -59,10 +134,16 @@ module VChainClient
|
|
59
134
|
end
|
60
135
|
|
61
136
|
def get_credentials_hash(document)
|
62
|
-
if document["type"] ==
|
137
|
+
if document["type"] == FIELD_TYPE_TRAVEL_DOCUMENT_HASHED
|
63
138
|
what_to_hash = document["type"] + document["citizenship"] + document["number"] + document["first_name"] + document["last_name"] + document["birthdate"]
|
64
139
|
|
65
140
|
return Digest::SHA512.hexdigest(what_to_hash)
|
141
|
+
|
142
|
+
elsif document["type"] == FIELD_TYPE_TEST_DOCUMENT_HASHED
|
143
|
+
what_to_hash = document["type"] + document["a"] + document["b"] + document["c"]
|
144
|
+
|
145
|
+
return Digest::SHA512.hexdigest(what_to_hash)
|
146
|
+
|
66
147
|
end
|
67
148
|
|
68
149
|
if @log.error?
|
@@ -112,83 +193,36 @@ module VChainClient
|
|
112
193
|
return previous_parent
|
113
194
|
end
|
114
195
|
|
115
|
-
def
|
116
|
-
|
117
|
-
client_id = @config["client_id"]
|
118
|
-
api_url = @config["api"]["url"] + "v0.1/use/";
|
119
|
-
|
120
|
-
document = input
|
121
|
-
document = self.cut(document)
|
122
|
-
document = self.hash(document)
|
196
|
+
def add_data_point(point_type, input, weight)
|
123
197
|
|
124
|
-
|
125
|
-
|
126
|
-
@log.debug("[use] hashed input:")
|
127
|
-
@log.debug(document)
|
128
|
-
end
|
129
|
-
|
130
|
-
document["client_id"] = client_id
|
131
|
-
document["ignore_possible_matches"] = ignore_possible_matches
|
132
|
-
|
133
|
-
if @log.debug?
|
134
|
-
@log.debug("[use] send_data:")
|
135
|
-
@log.debug(document)
|
136
|
-
end
|
137
|
-
|
138
|
-
begin
|
139
|
-
|
140
|
-
req = RestClient.post(api_url,
|
141
|
-
document.to_json,
|
142
|
-
{'Content-Type' => 'application/json'})
|
198
|
+
client_id = @config["client_id"]
|
199
|
+
api_url = @config["api"]["url"] + "v0.1/addDataPoint/"
|
143
200
|
|
144
|
-
|
201
|
+
time = Time.now.getutc
|
202
|
+
timestamp = time.to_i
|
145
203
|
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
@log.error("-> document:")
|
152
|
-
@log.error(document)
|
153
|
-
end
|
204
|
+
document = input
|
205
|
+
|
206
|
+
document = self.hash(document)
|
207
|
+
|
208
|
+
document = self.cut(document)
|
154
209
|
|
155
|
-
|
210
|
+
doc_hash = self.get_doc_hash(document)
|
156
211
|
|
157
|
-
|
212
|
+
if weight > 1
|
213
|
+
|
214
|
+
weight = 1
|
158
215
|
|
159
|
-
|
216
|
+
elsif weight < 0
|
160
217
|
|
161
|
-
|
162
|
-
if @log.error?
|
163
|
-
@log.error("[use] RestClient.post raised exception")
|
164
|
-
@log.error("#{e.class}, #{e.message}")
|
165
|
-
@log.error("-> ignore_possible_matches: #{ignore_possible_matches}")
|
166
|
-
@log.error("-> client_id: #{client_id}")
|
167
|
-
@log.error("-> api_url: #{api_url}")
|
168
|
-
@log.error("-> document:")
|
169
|
-
@log.error(document)
|
170
|
-
end
|
218
|
+
weight = 0
|
171
219
|
|
172
|
-
raise e
|
173
220
|
end
|
174
221
|
|
175
|
-
end
|
176
|
-
|
177
|
-
def do_verify(verification_type, input)
|
178
|
-
|
179
|
-
client_id = @config["client_id"]
|
180
|
-
api_url = @config["api"]["url"] + "v0.1/verify/"
|
181
|
-
|
182
|
-
time = Time.now.getutc
|
183
|
-
timestamp = time.to_i
|
184
|
-
|
185
|
-
document = input
|
186
|
-
document = self.cut(document)
|
187
|
-
document = self.hash(document)
|
188
|
-
|
189
222
|
if @log.debug?
|
190
223
|
@log.debug("[verify] will call "+ api_url +" using vchain_client_id "+ client_id)
|
191
|
-
@log.debug("->
|
224
|
+
@log.debug("-> point_type: "+ point_type)
|
225
|
+
@log.debug("-> weight: "+ weight.to_s)
|
192
226
|
@log.debug("-> timestamp: "+ timestamp.to_s)
|
193
227
|
@log.debug("-> hashed input:")
|
194
228
|
@log.debug(document)
|
@@ -196,17 +230,18 @@ module VChainClient
|
|
196
230
|
|
197
231
|
signaturesHelper = VChainClient::Signatures.new(@config)
|
198
232
|
|
199
|
-
|
233
|
+
point_signatures = nil
|
200
234
|
|
201
235
|
begin
|
202
236
|
|
203
|
-
|
237
|
+
point_signatures = signaturesHelper.signDataPoint(point_type, document, doc_hash, weight, timestamp)
|
204
238
|
|
205
239
|
rescue => e
|
206
240
|
if @log.error?
|
207
241
|
@log.error("[verify] Signatures.signVerification raised exception")
|
208
242
|
@log.error("#{e.class}, #{e.message}")
|
209
|
-
@log.error("->
|
243
|
+
@log.error("-> point_type: "+ point_type)
|
244
|
+
@log.error("-> weight: "+ weight.to_s)
|
210
245
|
@log.error("-> timestamp: "+ timestamp.to_s)
|
211
246
|
@log.error("-> client_id: #{client_id}")
|
212
247
|
@log.error("-> api_url: #{api_url}")
|
@@ -217,10 +252,11 @@ module VChainClient
|
|
217
252
|
raise e
|
218
253
|
end
|
219
254
|
|
220
|
-
if
|
255
|
+
if point_signatures == nil
|
221
256
|
if @log.error?
|
222
257
|
@log.error("[verify] failed to Signatures.signVerification")
|
223
|
-
@log.error("->
|
258
|
+
@log.error("-> point_type: "+ point_type)
|
259
|
+
@log.error("-> weight: "+ weight.to_s)
|
224
260
|
@log.error("-> timestamp: "+ timestamp.to_s)
|
225
261
|
@log.error("-> client_id: #{client_id}")
|
226
262
|
@log.error("-> api_url: #{api_url}")
|
@@ -232,8 +268,8 @@ module VChainClient
|
|
232
268
|
end
|
233
269
|
|
234
270
|
if @log.debug?
|
235
|
-
@log.debug("[verify]
|
236
|
-
@log.debug(
|
271
|
+
@log.debug("[verify] point_signatures:")
|
272
|
+
@log.debug(point_signatures)
|
237
273
|
end
|
238
274
|
|
239
275
|
document = Hash[document.sort]
|
@@ -247,14 +283,15 @@ module VChainClient
|
|
247
283
|
|
248
284
|
begin
|
249
285
|
|
250
|
-
whole_signature = signaturesHelper.signRequest(document, timestamp)
|
286
|
+
whole_signature = signaturesHelper.signRequest(document, point_type, weight, timestamp)
|
251
287
|
|
252
288
|
rescue => e
|
253
289
|
|
254
290
|
if @log.error?
|
255
291
|
@log.error("[verify] Signatures.signRequest raised exception:")
|
256
292
|
@log.error("#{e.class}: #{e.message}")
|
257
|
-
@log.error("->
|
293
|
+
@log.error("-> point_type: #{point_type}")
|
294
|
+
@log.error("-> weight: "+ weight.to_s)
|
258
295
|
@log.error("-> timestamp: "+ timestamp.to_s)
|
259
296
|
@log.error("-> client_id: #{client_id}")
|
260
297
|
@log.error("-> api_url: #{api_url}")
|
@@ -270,7 +307,8 @@ module VChainClient
|
|
270
307
|
|
271
308
|
if @log.error?
|
272
309
|
@log.error("[verify] failed to sign request")
|
273
|
-
@log.error("->
|
310
|
+
@log.error("-> point_type: #{point_type}")
|
311
|
+
@log.error("-> weight: "+ weight.to_s)
|
274
312
|
@log.error("-> timestamp: "+ timestamp.to_s)
|
275
313
|
@log.error("-> client_id: #{client_id}")
|
276
314
|
@log.error("-> api_url: #{api_url}")
|
@@ -291,9 +329,10 @@ module VChainClient
|
|
291
329
|
send_data = {}
|
292
330
|
send_data["client_id"] = client_id
|
293
331
|
send_data["data"] = document
|
332
|
+
send_data["weight"] = weight.to_s
|
294
333
|
send_data["timestamp"] = timestamp.to_s
|
295
|
-
send_data["
|
296
|
-
send_data["
|
334
|
+
send_data["type"] = point_type;
|
335
|
+
send_data["point_signatures"] = point_signatures
|
297
336
|
send_data["signature"] = whole_signature
|
298
337
|
|
299
338
|
if @log.debug?
|
@@ -312,7 +351,8 @@ module VChainClient
|
|
312
351
|
@log.error("[verify] response with code "+ req.code.to_s)
|
313
352
|
@log.error("-> client_id: #{client_id}")
|
314
353
|
@log.error("-> api_url: #{api_url}")
|
315
|
-
@log.error("->
|
354
|
+
@log.error("-> point_type: #{point_type}")
|
355
|
+
@log.error("-> weight: "+ weight.to_s)
|
316
356
|
@log.error("-> timestamp: "+ timestamp.to_s)
|
317
357
|
@log.error("-> send_data:")
|
318
358
|
@log.error(send_data)
|
@@ -334,7 +374,8 @@ module VChainClient
|
|
334
374
|
@log.error("#{e.class}, #{e.message}")
|
335
375
|
@log.error("-> client_id: #{client_id}")
|
336
376
|
@log.error("-> api_url: #{api_url}")
|
337
|
-
@log.error("->
|
377
|
+
@log.error("-> point_type: #{point_type}")
|
378
|
+
@log.error("-> weight: "+ weight.to_s)
|
338
379
|
@log.error("-> timestamp: "+ timestamp.to_s)
|
339
380
|
@log.error("-> send_data:")
|
340
381
|
@log.error(send_data)
|
@@ -344,19 +385,22 @@ module VChainClient
|
|
344
385
|
end
|
345
386
|
end
|
346
387
|
|
347
|
-
def
|
388
|
+
def check(input, is_already_hashed=false)
|
348
389
|
|
349
390
|
client_id = @config["client_id"]
|
391
|
+
|
350
392
|
api_url = @config["api"]["url"] + "v0.1/check/";
|
351
393
|
|
352
394
|
document = input
|
353
395
|
|
354
|
-
document = self.cut(document)
|
355
|
-
|
356
396
|
if (!is_already_hashed)
|
357
|
-
|
397
|
+
document = self.hash(document)
|
358
398
|
end
|
359
399
|
|
400
|
+
document = self.cut(document)
|
401
|
+
|
402
|
+
sent_document = document.clone
|
403
|
+
|
360
404
|
document["client_id"] = client_id
|
361
405
|
|
362
406
|
if @log.debug?
|
@@ -380,7 +424,7 @@ module VChainClient
|
|
380
424
|
@log.error("[check] response with code "+ req.code.to_s)
|
381
425
|
@log.error("-> client_id: #{client_id}")
|
382
426
|
@log.error("-> api_url: #{api_url}")
|
383
|
-
@log.
|
427
|
+
@log.error("-> is_already_hashed: #{is_already_hashed}")
|
384
428
|
@log.error("-> sent data:")
|
385
429
|
@log.error(document)
|
386
430
|
end
|
@@ -395,7 +439,7 @@ module VChainClient
|
|
395
439
|
@log.error("#{e.class}, #{e.message}")
|
396
440
|
@log.error("-> client_id: #{client_id}")
|
397
441
|
@log.error("-> api_url: #{api_url}")
|
398
|
-
@log.
|
442
|
+
@log.error("-> is_already_hashed: #{is_already_hashed}")
|
399
443
|
@log.error("-> sent data:")
|
400
444
|
@log.error(document)
|
401
445
|
end
|
@@ -403,800 +447,823 @@ module VChainClient
|
|
403
447
|
raise e
|
404
448
|
end
|
405
449
|
|
450
|
+
res = JSON.parse req.body
|
451
|
+
|
406
452
|
if @log.debug?
|
407
|
-
@log.debug("
|
453
|
+
@log.debug("response:")
|
408
454
|
@log.debug(req.body)
|
409
455
|
end
|
410
456
|
|
411
|
-
res
|
457
|
+
if res["status"].downcase == "error"
|
412
458
|
|
413
|
-
|
414
|
-
|
415
|
-
|
459
|
+
return {
|
460
|
+
"status" => "error",
|
461
|
+
"reason" => res["error_reason_code"]
|
462
|
+
}
|
416
463
|
|
417
|
-
|
464
|
+
else
|
418
465
|
|
419
|
-
|
420
|
-
@log.debug("[check] recieved verifications")
|
421
|
-
end
|
466
|
+
# success result
|
422
467
|
|
423
|
-
|
468
|
+
res_docs_index = {}
|
424
469
|
|
425
|
-
|
426
|
-
if res["error_reason_code"] == "DOCUMENT_POSSIBLE_MISTAKES"
|
427
|
-
credentials_document = {}
|
470
|
+
res["docs"].each { |res_doc|
|
428
471
|
|
429
|
-
|
472
|
+
res_doc_credentials_hash = self.get_credentials_hash(res_doc)
|
430
473
|
|
431
|
-
|
432
|
-
|
433
|
-
credentials_document[field] = res_document["values"][field]
|
434
|
-
else
|
435
|
-
credentials_document[field] = document[field]
|
436
|
-
end
|
437
|
-
}
|
474
|
+
if !res_docs_index.key?(res_doc_credentials_hash)
|
475
|
+
res_docs_index[res_doc_credentials_hash] = []
|
438
476
|
end
|
439
|
-
end
|
440
477
|
|
441
|
-
|
478
|
+
res_docs_index[res_doc_credentials_hash].push(res_doc)
|
479
|
+
}
|
480
|
+
|
481
|
+
validated_data_points = self.validate_data_points(res["data_points"], res["docs"])
|
482
|
+
|
483
|
+
if validated_data_points.length == 0
|
484
|
+
|
485
|
+
# not found
|
486
|
+
|
487
|
+
result = {}
|
488
|
+
|
489
|
+
sent_document.each { |field, value|
|
490
|
+
result[field] = 0
|
491
|
+
}
|
492
|
+
|
493
|
+
return {
|
494
|
+
"status" => "success",
|
495
|
+
"validated" => result
|
496
|
+
}
|
442
497
|
|
443
|
-
if @log.debug?
|
444
|
-
@log.debug("[check] credentials_hash: "+ credentials_hash)
|
445
498
|
end
|
446
499
|
|
447
|
-
|
500
|
+
# analyse
|
448
501
|
|
449
|
-
|
502
|
+
sent_doc_hash = self.get_doc_hash(sent_document)
|
450
503
|
|
451
|
-
|
504
|
+
sent_credentials_hash = self.get_credentials_hash(sent_document)
|
452
505
|
|
453
|
-
|
454
|
-
if v.key?("verifications") && v["verifications"].length > 0 && field != "type"
|
455
|
-
|
456
|
-
if @log.debug?
|
457
|
-
@log.debug("[check] check recieved verifications for '"+ field +"', number of recieved verifications: "+ v["verifications"].length.to_s)
|
458
|
-
end
|
506
|
+
hashed_sent_doc = self.full_hash(sent_document)
|
459
507
|
|
460
|
-
|
508
|
+
hashed_sent_doc_hash = Digest::SHA512.hexdigest(sent_doc_hash)
|
461
509
|
|
462
|
-
|
463
|
-
@log.debug("[check] field '"+ field +"', verification:")
|
464
|
-
@log.debug(verification)
|
465
|
-
end
|
510
|
+
# trying to find exact match by doc_hash
|
466
511
|
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
@log.error(verification)
|
471
|
-
@log.error(document)
|
472
|
-
end
|
512
|
+
if validated_data_points.key?(hashed_sent_doc_hash)
|
513
|
+
|
514
|
+
# exact match found by doc_hash
|
473
515
|
|
474
|
-
|
475
|
-
end
|
516
|
+
result = {}
|
476
517
|
|
477
|
-
|
478
|
-
if @log.error?
|
479
|
-
@log.error("[check] not a valid verification - blockchain_reciepts is empty")
|
480
|
-
@log.error("field '"+ field +"'")
|
481
|
-
@log.error(verification)
|
482
|
-
@log.error(document)
|
483
|
-
end
|
518
|
+
exact_match = validated_data_points[hashed_sent_doc_hash]
|
484
519
|
|
485
|
-
|
486
|
-
|
520
|
+
sent_document.each { |field, value|
|
521
|
+
|
522
|
+
hashed_field = Digest::SHA512.hexdigest(field)
|
487
523
|
|
488
|
-
|
489
|
-
if credentials_hash != verification["credentials_hash"]
|
490
|
-
if @log.error?
|
491
|
-
@log.error("[check] not a valid verification - credentials_hash mismatch ("+ credentials_hash +")")
|
492
|
-
@log.error("field '"+ field +"'")
|
493
|
-
@log.error(verification)
|
494
|
-
@log.error(document)
|
495
|
-
end
|
524
|
+
if exact_match.key?(hashed_field)
|
496
525
|
|
497
|
-
|
498
|
-
end
|
526
|
+
result[field] = exact_match[hashed_field]
|
499
527
|
|
500
|
-
|
501
|
-
field_hash = Digest::SHA512.hexdigest(field)
|
502
|
-
if field_hash != verification["field_hash"]
|
503
|
-
if @log.error?
|
504
|
-
@log.error("[check] not a valid verification - field_hash mismatch ("+ field_hash +")")
|
505
|
-
@log.error("field '"+ field +"'")
|
506
|
-
@log.error(verification)
|
507
|
-
@log.error(document)
|
508
|
-
end
|
528
|
+
else
|
509
529
|
|
510
|
-
|
511
|
-
end
|
530
|
+
result[field] = 0
|
512
531
|
|
513
|
-
|
514
|
-
data_hash = Digest::SHA512.hexdigest(document[field])
|
515
|
-
if res.key?("document")
|
516
|
-
if res["document"].key?("values")
|
517
|
-
if res["document"]["values"].key?(field)
|
518
|
-
if res["document"]["values"][field] != document[field]
|
519
|
-
data_hash = Digest::SHA512.hexdigest(res["document"]["values"][field])
|
520
|
-
end
|
521
|
-
end
|
522
|
-
end
|
523
|
-
end
|
524
|
-
if data_hash != verification["data_hash"]
|
525
|
-
if @log.error?
|
526
|
-
@log.error("[check] not a valid verification - data_hash mismatch ("+ data_hash +")")
|
527
|
-
@log.error("field '"+ field +"'")
|
528
|
-
@log.error(verification)
|
529
|
-
@log.error(document)
|
530
|
-
end
|
532
|
+
end
|
531
533
|
|
532
|
-
|
533
|
-
end
|
534
|
+
}
|
534
535
|
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
if @log.error?
|
540
|
-
@log.error("[check] not a valid verification - checksum mismatch ("+ checksum +")")
|
541
|
-
@log.error("field '"+ field +"'")
|
542
|
-
@log.error(verification)
|
543
|
-
@log.error(document)
|
544
|
-
@log.error(credentials_hash)
|
545
|
-
@log.error(field_hash)
|
546
|
-
@log.error(data_hash)
|
547
|
-
end
|
536
|
+
return {
|
537
|
+
"status" => "success",
|
538
|
+
"validated" => result
|
539
|
+
}
|
548
540
|
|
549
|
-
|
550
|
-
end
|
541
|
+
else
|
551
542
|
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
543
|
+
# search by credentials_hash
|
544
|
+
|
545
|
+
found_docs = []
|
546
|
+
if res_docs_index.key?(sent_credentials_hash)
|
547
|
+
found_docs = res_docs_index[sent_credentials_hash]
|
548
|
+
end
|
556
549
|
|
557
|
-
|
558
|
-
# first element
|
559
|
-
reciepts_validated = 0
|
560
|
-
verification["blockchain_reciepts"].each { |reciept|
|
550
|
+
if found_docs.length > 0
|
561
551
|
|
562
|
-
|
563
|
-
@log.debug("reciept to check:")
|
564
|
-
@log.debug(reciept)
|
565
|
-
end
|
552
|
+
# matches found by credentials
|
566
553
|
|
567
|
-
|
568
|
-
if @log.error?
|
569
|
-
@log.error("[check] not a valid blockchain reciept - no target_proof")
|
570
|
-
@log.error(reciept)
|
571
|
-
@log.error("field '"+ field +"'")
|
572
|
-
@log.error(verification)
|
573
|
-
@log.error(document)
|
574
|
-
end
|
554
|
+
result = {}
|
575
555
|
|
576
|
-
|
577
|
-
end
|
556
|
+
possible_mistakes = []
|
578
557
|
|
579
|
-
|
580
|
-
if @log.error?
|
581
|
-
@log.error("[check] not a valid blockchain reciept - target_proof length is <= 0")
|
582
|
-
@log.error(reciept)
|
583
|
-
@log.error("field '"+ field +"'")
|
584
|
-
@log.error(verification)
|
585
|
-
@log.error(document)
|
586
|
-
end
|
558
|
+
cred_fields = self.get_credentials_fields(sent_document["type"]);
|
587
559
|
|
588
|
-
|
589
|
-
end
|
560
|
+
non_cred_fields_index = {}
|
590
561
|
|
591
|
-
|
592
|
-
if @log.error?
|
593
|
-
@log.error("[check] not a valid blockchain reciept - no target element in target_proof.0")
|
594
|
-
@log.error(reciept)
|
595
|
-
@log.error("field '"+ field +"'")
|
596
|
-
@log.error(verification)
|
597
|
-
@log.error(document)
|
598
|
-
end
|
562
|
+
found_docs.each { |cred_doc|
|
599
563
|
|
600
|
-
|
564
|
+
cred_doc_hash = self.get_doc_hash(cred_doc)
|
565
|
+
cred_doc_hash = Digest::SHA512.hexdigest(cred_doc_hash)
|
566
|
+
|
567
|
+
cred_doc_exact_match = validated_data_points[cred_doc_hash]
|
568
|
+
|
569
|
+
# fill credential fields
|
570
|
+
cred_fields.each { |cred_field|
|
571
|
+
|
572
|
+
cred_field_hashed = Digest::SHA512.hexdigest(cred_field)
|
573
|
+
|
574
|
+
if !result.key?(cred_field)
|
575
|
+
result[cred_field] = 0
|
601
576
|
end
|
602
577
|
|
603
|
-
|
604
|
-
|
605
|
-
# now,
|
606
|
-
|
607
|
-
# 3. check tree convergence to root hash
|
608
|
-
# and compare this computed root hash
|
609
|
-
# with merkle_tree_root_hash from response
|
610
|
-
if @log.debug?
|
611
|
-
@log.debug("will now build merkle tree with")
|
612
|
-
@log.debug(reciept["target_proof"])
|
613
|
-
@log.debug(reciept["timestamp"])
|
578
|
+
if cred_doc_exact_match.key?(cred_field_hashed)
|
579
|
+
result[cred_field] += cred_doc_exact_match[cred_field_hashed]
|
614
580
|
end
|
615
581
|
|
616
|
-
|
582
|
+
}
|
583
|
+
|
584
|
+
# fill non credential fields
|
585
|
+
cred_doc.each { |field, value|
|
617
586
|
|
618
|
-
if
|
619
|
-
@log.debug("computed tree root hash = "+ computed_tree_root_hash)
|
620
|
-
end
|
587
|
+
if !cred_fields.include?(field) && field != "doc_hash"
|
621
588
|
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
@log.error("field '"+ field +"'")
|
627
|
-
@log.error(verification)
|
628
|
-
@log.error(document)
|
589
|
+
non_cred_field_hashed = Digest::SHA512.hexdigest(field)
|
590
|
+
|
591
|
+
if !non_cred_fields_index.key?(field)
|
592
|
+
non_cred_fields_index[field] = {}
|
629
593
|
end
|
630
594
|
|
631
|
-
|
632
|
-
|
633
|
-
if computed_tree_root_hash != reciept["merkle_tree_root_hash"]
|
634
|
-
if @log.error?
|
635
|
-
@log.error("[check] not a valid blockchain reciept - merkle tree root hash mismatch ("+ computed_tree_root_hash +", "+ reciept["merkle_tree_root_hash"] +")")
|
636
|
-
@log.error(reciept)
|
637
|
-
@log.error("field '"+ field +"'")
|
638
|
-
@log.error(verification)
|
639
|
-
@log.error(document)
|
595
|
+
if !non_cred_fields_index[field].key?(value)
|
596
|
+
non_cred_fields_index[field][value] = 0
|
640
597
|
end
|
641
598
|
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
last_proof_index = reciept["target_proof"].length - 1
|
646
|
-
reciept_stored_last_parent = reciept["target_proof"][last_proof_index]["parent"]
|
647
|
-
if reciept_stored_last_parent != computed_tree_root_hash
|
648
|
-
if @log.error?
|
649
|
-
@log.error("[check] not a valid blockchain reciept - last stored parent != computed_tree_root_hash ("+ reciept_stored_last_parent +", "+ computed_tree_root_hash +")")
|
650
|
-
@log.error(reciept)
|
651
|
-
@log.error("field '"+ field +"'")
|
652
|
-
@log.error(verification)
|
653
|
-
@log.error(document)
|
599
|
+
if cred_doc_exact_match.key?(non_cred_field_hashed)
|
600
|
+
non_cred_fields_index[field][value] += cred_doc_exact_match[non_cred_field_hashed]
|
654
601
|
end
|
655
602
|
|
656
|
-
break
|
657
603
|
end
|
658
604
|
|
659
|
-
|
660
|
-
# compare it to computed root hash of a tree
|
661
|
-
# retrieve some info from tx to verify signature
|
662
|
-
tx = nil
|
663
|
-
|
664
|
-
begin
|
665
|
-
|
666
|
-
tx = blockchainConnection.getTx(reciept["blockchain_txid"])
|
667
|
-
|
668
|
-
rescue => e
|
669
|
-
if @log.error?
|
670
|
-
@log.error("[check] BlockchainConnection.getTx raised exception:")
|
671
|
-
@log.error("#{e.class}, #{e.message}")
|
672
|
-
@log.error("-> client_id: #{client_id}")
|
673
|
-
@log.error("-> api_url: #{api_url}")
|
674
|
-
@log.error("-> is_already_hashed: #{is_already_hashed}")
|
675
|
-
@log.error("-> sent data:")
|
676
|
-
@log.error(document)
|
677
|
-
@log.error("--> blockchain_txid: "+ reciept["blockchain_txid"])
|
678
|
-
end
|
605
|
+
}
|
679
606
|
|
680
|
-
|
681
|
-
end
|
607
|
+
}
|
682
608
|
|
609
|
+
non_cred_fields_index.each { |field, values|
|
683
610
|
|
684
|
-
|
685
|
-
@log.debug("[check] tx ["+ reciept["blockchain_txid"] +"]:")
|
686
|
-
@log.debug(tx)
|
687
|
-
end
|
611
|
+
if values.length == 1
|
688
612
|
|
689
|
-
|
690
|
-
if
|
691
|
-
|
692
|
-
|
693
|
-
|
694
|
-
@log.error(verification)
|
695
|
-
@log.error(document)
|
613
|
+
values.take(1).each { |value, validated_count|
|
614
|
+
if value == sent_document[field]
|
615
|
+
result[field] = validated_count
|
616
|
+
else
|
617
|
+
possible_mistakes.push(field)
|
696
618
|
end
|
619
|
+
}
|
697
620
|
|
698
|
-
|
699
|
-
|
621
|
+
else
|
622
|
+
possible_mistakes.push(field)
|
623
|
+
end
|
700
624
|
|
701
|
-
|
702
|
-
if @log.error?
|
703
|
-
@log.error("[check] not a valid blockchain reciept - block_hash mismatch")
|
704
|
-
@log.error(tx)
|
705
|
-
@log.error(reciept)
|
706
|
-
@log.error("field '"+ field +"'")
|
707
|
-
@log.error(verification)
|
708
|
-
@log.error(document)
|
709
|
-
end
|
625
|
+
}
|
710
626
|
|
711
|
-
|
712
|
-
|
627
|
+
return {
|
628
|
+
"status" => "success",
|
629
|
+
"possible_mistakes" => possible_mistakes,
|
630
|
+
"validated" => result
|
631
|
+
}
|
713
632
|
|
714
|
-
|
715
|
-
if @log.error?
|
716
|
-
@log.error("[check] not a valid blockchain reciept - timestamp mismatch")
|
717
|
-
@log.error(tx)
|
718
|
-
@log.error(reciept)
|
719
|
-
@log.error("field '"+ field +"'")
|
720
|
-
@log.error(verification)
|
721
|
-
@log.error(document)
|
722
|
-
end
|
633
|
+
else
|
723
634
|
|
724
|
-
|
725
|
-
end
|
635
|
+
# search for possible errors in credentials
|
726
636
|
|
727
|
-
|
728
|
-
if @log.error?
|
729
|
-
@log.error("[check] not a valid blockchain reciept - op_return mismatch")
|
730
|
-
@log.error(computed_tree_root_hash)
|
731
|
-
@log.error(tx)
|
732
|
-
@log.error(reciept)
|
733
|
-
@log.error("field '"+ field +"'")
|
734
|
-
@log.error(verification)
|
735
|
-
@log.error(document)
|
736
|
-
end
|
637
|
+
similar_sets = self.get_similar_credential_sets(sent_document["type"])
|
737
638
|
|
738
|
-
|
739
|
-
|
639
|
+
result = {}
|
640
|
+
possible_mistakes = []
|
740
641
|
|
741
|
-
|
742
|
-
blockchain_block_hash = tx["block_hash"];
|
743
|
-
blockchain_timestamp = tx["block_timestamp"];
|
744
|
-
|
745
|
-
if @log.debug?
|
746
|
-
@log.debug(blockchain_txid)
|
747
|
-
@log.debug(blockchain_block_hash)
|
748
|
-
@log.debug(blockchain_timestamp)
|
749
|
-
end
|
642
|
+
other_fields_index = {}
|
750
643
|
|
751
|
-
|
752
|
-
# a) federative server record in Blockstack (recursive)
|
753
|
-
# b) tree_signature
|
754
|
-
|
755
|
-
# a) federative server record in Blockstack (recursive)
|
756
|
-
begin
|
757
|
-
|
758
|
-
if !blockstackClient.checkFederativeServer(reciept["federative_server_id"])
|
759
|
-
if @log.error?
|
760
|
-
@log.error("[check] not a valid blockchain reciept - failed to check federative server")
|
761
|
-
@log.error("-> client_id: #{client_id}")
|
762
|
-
@log.error("-> api_url: #{api_url}")
|
763
|
-
@log.error("-> is_already_hashed: #{is_already_hashed}")
|
764
|
-
@log.error("-> sent data:")
|
765
|
-
@log.error(document)
|
766
|
-
@log.error("--> federative_server_id: "+ reciept["federative_server_id"])
|
767
|
-
end
|
644
|
+
similar_sets.each { |lookup_set|
|
768
645
|
|
769
|
-
|
770
|
-
end
|
646
|
+
lookup_set_match_found = false
|
771
647
|
|
772
|
-
|
773
|
-
if @log.error?
|
774
|
-
@log.error("[check] Blockstack.checkFederativeServer raised exception:")
|
775
|
-
@log.error("#{e.class}, #{e.message}")
|
776
|
-
@log.error("-> client_id: #{client_id}")
|
777
|
-
@log.error("-> api_url: #{api_url}")
|
778
|
-
@log.error("-> is_already_hashed: #{is_already_hashed}")
|
779
|
-
@log.error("-> sent data:")
|
780
|
-
@log.error(document)
|
781
|
-
@log.error("--> federative_server_id: "+ reciept["federative_server_id"])
|
782
|
-
end
|
648
|
+
res["docs"].each { |res_doc|
|
783
649
|
|
784
|
-
|
785
|
-
end
|
650
|
+
is_matching = true
|
786
651
|
|
787
|
-
|
788
|
-
|
652
|
+
lookup_set.each { |lookup_field|
|
653
|
+
sent_doc_val = sent_document[lookup_field]
|
654
|
+
res_doc_val = res_doc[lookup_field]
|
789
655
|
|
790
|
-
|
791
|
-
|
792
|
-
|
793
|
-
|
794
|
-
rescue => e
|
795
|
-
if @log.error?
|
796
|
-
@log.error("[check] Blockstack.getPublicKey raised exception:")
|
797
|
-
@log.error("#{e.class}, #{e.message}")
|
798
|
-
@log.error("-> client_id: #{client_id}")
|
799
|
-
@log.error("-> api_url: #{api_url}")
|
800
|
-
@log.error("-> is_already_hashed: #{is_already_hashed}")
|
801
|
-
@log.error("-> sent data:")
|
802
|
-
@log.error(document)
|
803
|
-
@log.error("--> federative_server_id: "+ reciept["federative_server_id"])
|
656
|
+
if sent_doc_val != res_doc_val
|
657
|
+
is_matching = false
|
658
|
+
break
|
804
659
|
end
|
660
|
+
}
|
805
661
|
|
806
|
-
|
807
|
-
|
662
|
+
if is_matching
|
663
|
+
matching_doc_hash = self.get_doc_hash(res_doc)
|
664
|
+
matching_doc_hash = Digest::SHA512.hexdigest(matching_doc_hash)
|
808
665
|
|
809
|
-
|
810
|
-
if @log.error?
|
811
|
-
@log.error("[check] not a valid blockchain reciept - failed to retrieve public key for federative server '"+ reciept["federative_server_id"] +"'")
|
812
|
-
@log.error("-> client_id: #{client_id}")
|
813
|
-
@log.error("-> api_url: #{api_url}")
|
814
|
-
@log.error("-> is_already_hashed: #{is_already_hashed}")
|
815
|
-
@log.error("-> sent data:")
|
816
|
-
@log.error(document)
|
817
|
-
@log.error("--> federative_server_id: "+ reciept["federative_server_id"])
|
818
|
-
end
|
666
|
+
matching_exact_match = validated_data_points[matching_doc_hash]
|
819
667
|
|
820
|
-
|
821
|
-
end
|
822
|
-
|
823
|
-
if @log.debug?
|
824
|
-
@log.debug("federative server pubkey:")
|
825
|
-
@log.debug(federative_server_pubkey)
|
826
|
-
end
|
668
|
+
lookup_set.each { |lookup_field|
|
827
669
|
|
828
|
-
|
829
|
-
|
830
|
-
if !signaturesHelper.checkTreeSignature(computed_tree_root_hash, blockchain_txid, blockchain_block_hash, blockchain_timestamp, reciept["federative_server_id"], reciept["federative_server_version"], Base64.decode64(reciept["tree_signature"]), federative_server_pubkey)
|
831
|
-
if @log.error?
|
832
|
-
@log.error("[check] not a valid blockchain reciept - failed to verify tree signature")
|
833
|
-
@log.error("-> client_id: #{client_id}")
|
834
|
-
@log.error("-> api_url: #{api_url}")
|
835
|
-
@log.debug("-> is_already_hashed: #{is_already_hashed}")
|
836
|
-
@log.error("-> sent data:")
|
837
|
-
@log.error(document)
|
838
|
-
@log.error("--> computed_tree_root_hash: #{computed_tree_root_hash}")
|
839
|
-
@log.error("--> blockchain_txid: #{blockchain_txid}")
|
840
|
-
@log.error("--> blockchain_block_hash: #{blockchain_block_hash}")
|
841
|
-
@log.error("--> blockchain_timestamp: #{blockchain_timestamp}")
|
842
|
-
@log.error("--> federative_server_id: "+ reciept["federative_server_id"])
|
843
|
-
@log.error("--> federative_server_version: "+ reciept["federative_server_version"])
|
844
|
-
@log.error("--> tree_signature: "+ Base64.decode64(reciept["tree_signature"]))
|
845
|
-
@log.error("--> federative_server_pubkey: #{federative_server_pubkey}")
|
846
|
-
end
|
670
|
+
lookup_field_hashed = Digest::SHA512.hexdigest(lookup_field)
|
847
671
|
|
848
|
-
|
849
|
-
|
672
|
+
result[lookup_field] = matching_exact_match[lookup_field_hashed]
|
673
|
+
}
|
850
674
|
|
851
|
-
|
852
|
-
|
853
|
-
|
854
|
-
@log.error("#{e.class}, #{e.message}")
|
855
|
-
@log.error("-> client_id: #{client_id}")
|
856
|
-
@log.error("-> api_url: #{api_url}")
|
857
|
-
@log.debug("-> is_already_hashed: #{is_already_hashed}")
|
858
|
-
@log.error("-> sent data:")
|
859
|
-
@log.error(document)
|
860
|
-
@log.error("--> computed_tree_root_hash: #{computed_tree_root_hash}")
|
861
|
-
@log.error("--> blockchain_txid: #{blockchain_txid}")
|
862
|
-
@log.error("--> blockchain_block_hash: #{blockchain_block_hash}")
|
863
|
-
@log.error("--> blockchain_timestamp: #{blockchain_timestamp}")
|
864
|
-
@log.error("--> federative_server_id: "+ reciept["federative_server_id"])
|
865
|
-
@log.error("--> federative_server_version: "+ reciept["federative_server_version"])
|
866
|
-
@log.error("--> tree_signature: "+ Base64.decode64(reciept["tree_signature"]))
|
867
|
-
@log.error("--> federative_server_pubkey: #{federative_server_pubkey}")
|
868
|
-
end
|
675
|
+
res_doc.each { |field, value|
|
676
|
+
|
677
|
+
if !lookup_set.include?(field) && field != "doc_hash"
|
869
678
|
|
870
|
-
|
871
|
-
|
679
|
+
other_field_hashed = Digest::SHA512.hexdigest(field)
|
680
|
+
|
681
|
+
if !other_fields_index.key?(field)
|
682
|
+
other_fields_index[field] = {}
|
683
|
+
end
|
872
684
|
|
873
|
-
|
874
|
-
|
685
|
+
if !other_fields_index[field].key?(value)
|
686
|
+
other_fields_index[field][value] = 0
|
687
|
+
end
|
875
688
|
|
876
|
-
|
877
|
-
|
878
|
-
|
879
|
-
@log.error("field '"+ field +"'")
|
880
|
-
@log.error(verification)
|
881
|
-
@log.error(document)
|
882
|
-
end
|
689
|
+
if matching_exact_match.key?(other_field_hashed)
|
690
|
+
other_fields_index[field][value] += matching_exact_match[other_field_hashed]
|
691
|
+
end
|
883
692
|
|
884
|
-
|
885
|
-
end
|
693
|
+
end
|
886
694
|
|
887
|
-
|
888
|
-
# a) check verificator record in Blockstack (recursive)
|
889
|
-
# b) check validator record in Blockstack (recursive)
|
890
|
-
# c) verificator_sig
|
891
|
-
# d) validtor_sig
|
892
|
-
|
893
|
-
# a) check verificator record in Blockstack (recursive)
|
894
|
-
begin
|
895
|
-
|
896
|
-
if !blockstackClient.checkVerificator(verification["verificator_id"])
|
897
|
-
if @log.error?
|
898
|
-
@log.error("[check] not a valid verification - failed to check verificator record")
|
899
|
-
@log.error("-> client_id: #{client_id}")
|
900
|
-
@log.error("-> api_url: #{api_url}")
|
901
|
-
@log.error("-> is_already_hashed: #{is_already_hashed}")
|
902
|
-
@log.error("-> sent data:")
|
903
|
-
@log.error(document)
|
904
|
-
@log.error("--> verificator_id: "+ verification["verificator_id"])
|
905
|
-
end
|
695
|
+
}
|
906
696
|
|
907
|
-
|
697
|
+
lookup_set_match_found = true
|
908
698
|
end
|
909
699
|
|
910
|
-
|
911
|
-
|
912
|
-
@log.error("[check] Blockstack.checkVerificator raised exception:")
|
913
|
-
@log.error("#{e.class}, #{e.message}")
|
914
|
-
@log.error("-> client_id: #{client_id}")
|
915
|
-
@log.error("-> api_url: #{api_url}")
|
916
|
-
@log.error("-> is_already_hashed: #{is_already_hashed}")
|
917
|
-
@log.error("-> sent data:")
|
918
|
-
@log.error(document)
|
919
|
-
@log.error("--> verificator_id: "+ verification["verificator_id"])
|
700
|
+
if is_matching
|
701
|
+
break
|
920
702
|
end
|
703
|
+
}
|
921
704
|
|
922
|
-
|
705
|
+
if lookup_set_match_found
|
706
|
+
break
|
923
707
|
end
|
924
708
|
|
925
|
-
|
926
|
-
begin
|
927
|
-
|
928
|
-
if !blockstackClient.checkValidator(verification["validator_id"])
|
929
|
-
if @log.error?
|
930
|
-
@log.error("[check] not a valid verification - failed to check validator record")
|
931
|
-
@log.error("-> client_id: #{client_id}")
|
932
|
-
@log.error("-> api_url: #{api_url}")
|
933
|
-
@log.error("-> is_already_hashed: #{is_already_hashed}")
|
934
|
-
@log.error("-> sent data:")
|
935
|
-
@log.error(document)
|
936
|
-
@log.error("--> validator_id: "+ verification["validator_id"])
|
937
|
-
end
|
709
|
+
}
|
938
710
|
|
939
|
-
|
940
|
-
end
|
711
|
+
other_fields_index.each { |field, values|
|
941
712
|
|
942
|
-
|
943
|
-
if @log.error?
|
944
|
-
@log.error("[check] Blockstack.checkValidator raised exception:")
|
945
|
-
@log.error("#{e.class}, #{e.message}")
|
946
|
-
@log.error("-> client_id: #{client_id}")
|
947
|
-
@log.error("-> api_url: #{api_url}")
|
948
|
-
@log.error("-> is_already_hashed: #{is_already_hashed}")
|
949
|
-
@log.error("-> sent data:")
|
950
|
-
@log.error(document)
|
951
|
-
@log.error("--> validator_id: "+ verification["validator_id"])
|
952
|
-
end
|
713
|
+
if values.length == 1
|
953
714
|
|
954
|
-
|
715
|
+
values.take(1).each { |value, validated_count|
|
716
|
+
if value == sent_document[field]
|
717
|
+
result[field] = validated_count
|
718
|
+
else
|
719
|
+
possible_mistakes.push(field)
|
720
|
+
end
|
721
|
+
}
|
722
|
+
|
723
|
+
else
|
724
|
+
possible_mistakes.push(field)
|
955
725
|
end
|
956
726
|
|
957
|
-
|
958
|
-
verificator_pubkey = nil
|
727
|
+
}
|
959
728
|
|
960
|
-
|
729
|
+
return {
|
730
|
+
"status" => "success",
|
731
|
+
"possible_mistakes" => possible_mistakes,
|
732
|
+
"validated" => result
|
733
|
+
}
|
961
734
|
|
962
|
-
|
735
|
+
end
|
963
736
|
|
964
|
-
|
965
|
-
if @log.error?
|
966
|
-
@log.error("[check] Blockstack.getPublicKey raised exception:")
|
967
|
-
@log.error("#{e.class}, #{e.message}")
|
968
|
-
@log.error("-> client_id: #{client_id}")
|
969
|
-
@log.error("-> api_url: #{api_url}")
|
970
|
-
@log.error("-> is_already_hashed: #{is_already_hashed}")
|
971
|
-
@log.error("-> sent data:")
|
972
|
-
@log.error(document)
|
973
|
-
@log.error("--> verificator_id: "+ verification["verificator_id"])
|
974
|
-
end
|
737
|
+
end
|
975
738
|
|
976
|
-
|
977
|
-
|
739
|
+
end
|
740
|
+
end
|
978
741
|
|
979
|
-
|
980
|
-
if @log.error?
|
981
|
-
@log.error("[check] failed to retrieve public key for verificator")
|
982
|
-
@log.error("-> client_id: #{client_id}")
|
983
|
-
@log.error("-> api_url: #{api_url}")
|
984
|
-
@log.error("-> is_already_hashed: #{is_already_hashed}")
|
985
|
-
@log.error("-> sent data:")
|
986
|
-
@log.error(document)
|
987
|
-
@log.error("--> verificator_id: "+ verification["verificator_id"])
|
988
|
-
end
|
742
|
+
def validate_data_points(data_points, documents)
|
989
743
|
|
990
|
-
|
991
|
-
end
|
744
|
+
output = {}
|
992
745
|
|
993
|
-
|
994
|
-
@log.debug("verificator pubkey:")
|
995
|
-
@log.debug(verificator_pubkey)
|
996
|
-
end
|
746
|
+
blockchainConnection = VChainClient::BlockchainConnection.new(@config)
|
997
747
|
|
998
|
-
|
999
|
-
|
1000
|
-
if !signaturesHelper.checkVerificationSignature(field_hash, data_hash, verification["type"], verification["timestamp"], verification["verificator_id"], verificator_pubkey, Base64.decode64(verification["verificator_sig"]))
|
1001
|
-
if @log.error?
|
1002
|
-
@log.error("[check] not a valid verification - failed to check verificator signature")
|
1003
|
-
@log.error("-> client_id: #{client_id}")
|
1004
|
-
@log.error("-> api_url: #{api_url}")
|
1005
|
-
@log.error("-> is_already_hashed: #{is_already_hashed}")
|
1006
|
-
@log.error("-> sent data:")
|
1007
|
-
@log.error(document)
|
1008
|
-
@log.error("--> field_hash: #{field_hash}")
|
1009
|
-
@log.error("--> data_hash")
|
1010
|
-
@log.error("--> verification_type: "+ verification["type"])
|
1011
|
-
@log.error("--> verification_timestamp: "+ verification["timestamp"].to_s)
|
1012
|
-
@log.error("--> verificator_id: "+ verification["verificator_id"])
|
1013
|
-
@log.error("--> verificator_pubkey: "+ verificator_pubkey)
|
1014
|
-
@log.error("--> verificator_sig: "+ Base64.decode64(verification["verificator_sig"]))
|
1015
|
-
end
|
748
|
+
blockstackClient = VChainClient::BlockstackClient.new(@config)
|
1016
749
|
|
1017
|
-
|
1018
|
-
end
|
750
|
+
signaturesHelper = VChainClient::Signatures.new(@config)
|
1019
751
|
|
1020
|
-
|
1021
|
-
if @log.error?
|
1022
|
-
@log.error("[check] Signatures.checkVerificationSignature raised exception:")
|
1023
|
-
@log.error("#{e.class}, #{e.message}")
|
1024
|
-
@log.error("-> client_id: #{client_id}")
|
1025
|
-
@log.error("-> api_url: #{api_url}")
|
1026
|
-
@log.error("-> is_already_hashed: #{is_already_hashed}")
|
1027
|
-
@log.error("-> sent data:")
|
1028
|
-
@log.error(document)
|
1029
|
-
@log.error("--> field_hash: #{field_hash}")
|
1030
|
-
@log.error("--> data_hash")
|
1031
|
-
@log.error("--> verification_type: "+ verification["type"])
|
1032
|
-
@log.error("--> verification_timestamp: "+ verification["timestamp"].to_s)
|
1033
|
-
@log.error("--> verificator_id: "+ verification["verificator_id"])
|
1034
|
-
@log.error("--> verificator_pubkey: "+ verificator_pubkey)
|
1035
|
-
@log.error("--> verificator_sig: "+ Base64.decode64(verification["verificator_sig"]))
|
1036
|
-
end
|
752
|
+
documents_index = {}
|
1037
753
|
|
1038
|
-
|
1039
|
-
|
754
|
+
documents.each { |document|
|
755
|
+
hashed_doc = self.full_hash(document)
|
756
|
+
hashed_doc["original_doc_hash"] = self.get_doc_hash(document)
|
757
|
+
documents_index[hashed_doc["doc_hash"]] = hashed_doc
|
758
|
+
}
|
1040
759
|
|
1041
|
-
|
1042
|
-
validator_pubkey = nil
|
760
|
+
data_points.each { |data_point|
|
1043
761
|
|
1044
|
-
|
762
|
+
if !data_point.key?("blockchain_reciepts")
|
763
|
+
if @log.error?
|
764
|
+
@log.error("[check] not a valid data point - no blockchain_reciepts key")
|
765
|
+
@log.error(data_point)
|
766
|
+
end
|
1045
767
|
|
1046
|
-
|
768
|
+
next
|
769
|
+
end
|
1047
770
|
|
1048
|
-
|
1049
|
-
|
1050
|
-
|
1051
|
-
|
1052
|
-
|
1053
|
-
@log.error("-> api_url: #{api_url}")
|
1054
|
-
@log.error("-> is_already_hashed: #{is_already_hashed}")
|
1055
|
-
@log.error("-> sent data:")
|
1056
|
-
@log.error(document)
|
1057
|
-
@log.error("--> validator_id: "+ verification["validator_id"])
|
1058
|
-
end
|
771
|
+
if data_point["blockchain_reciepts"].length <= 0
|
772
|
+
if @log.error?
|
773
|
+
@log.error("[check] not a valid data point - blockchain_reciepts is empty")
|
774
|
+
@log.error(data_point)
|
775
|
+
end
|
1059
776
|
|
1060
|
-
|
1061
|
-
|
777
|
+
next
|
778
|
+
end
|
1062
779
|
|
1063
|
-
|
1064
|
-
|
1065
|
-
|
1066
|
-
|
1067
|
-
|
1068
|
-
@log.error("-> is_already_hashed: #{is_already_hashed}")
|
1069
|
-
@log.error("-> sent data:")
|
1070
|
-
@log.error(document)
|
1071
|
-
@log.error("--> validator_id: "+ verification["validator_id"])
|
1072
|
-
end
|
780
|
+
if !documents_index.key?(data_point["doc_hash"])
|
781
|
+
if @log.error?
|
782
|
+
@log.error("[check] not a valid data point - no such doc_hash in docs returned")
|
783
|
+
@log.error(data_point)
|
784
|
+
end
|
1073
785
|
|
1074
|
-
|
1075
|
-
|
786
|
+
next
|
787
|
+
end
|
1076
788
|
|
1077
|
-
|
1078
|
-
@log.debug("validator pubkey:")
|
1079
|
-
@log.debug(validator_pubkey)
|
1080
|
-
end
|
789
|
+
document = documents_index[data_point["doc_hash"]]
|
1081
790
|
|
1082
|
-
|
1083
|
-
|
1084
|
-
if !signaturesHelper.checkVerificationSignature(field_hash, data_hash, verification["type"], verification["timestamp"], verification["validator_id"], validator_pubkey, Base64.decode64(verification["validator_sig"]))
|
1085
|
-
if @log.error?
|
1086
|
-
@log.error("[check] not a valid verification - failed to check verificator signature")
|
1087
|
-
@log.error("-> client_id: #{client_id}")
|
1088
|
-
@log.error("-> api_url: #{api_url}")
|
1089
|
-
@log.error("-> is_already_hashed: #{is_already_hashed}")
|
1090
|
-
@log.error("-> sent data:")
|
1091
|
-
@log.error(document)
|
1092
|
-
@log.error("--> field_hash: #{field_hash}")
|
1093
|
-
@log.error("--> data_hash")
|
1094
|
-
@log.error("--> verification_type: "+ verification["type"])
|
1095
|
-
@log.error("--> verification_timestamp: "+ verification["timestamp"].to_s)
|
1096
|
-
@log.error("--> validator_id: "+ verification["validator_id"])
|
1097
|
-
@log.error("--> validator_pubkey: "+ validator_pubkey)
|
1098
|
-
@log.error("--> validator_sig: "+ Base64.decode64(verification["validator_sig"]))
|
1099
|
-
end
|
791
|
+
doc_hash = Digest::SHA512.hexdigest(document["original_doc_hash"])
|
1100
792
|
|
1101
|
-
|
1102
|
-
|
793
|
+
# 1a. check doc_hash
|
794
|
+
if doc_hash != data_point["doc_hash"]
|
795
|
+
if @log.error?
|
796
|
+
@log.error("[check] not a valid data point - doc_hash mismatch ("+ data_point["doc_hash"] +")")
|
797
|
+
end
|
1103
798
|
|
1104
|
-
|
1105
|
-
|
1106
|
-
@log.error("[check] Signatures.checkVerificationSignature raised exception:")
|
1107
|
-
@log.error("#{e.class}, #{e.message}")
|
1108
|
-
@log.error("-> client_id: #{client_id}")
|
1109
|
-
@log.error("-> api_url: #{api_url}")
|
1110
|
-
@log.error("-> is_already_hashed: #{is_already_hashed}")
|
1111
|
-
@log.error("-> sent data:")
|
1112
|
-
@log.error(document)
|
1113
|
-
@log.error("--> field_hash: #{field_hash}")
|
1114
|
-
@log.error("--> data_hash")
|
1115
|
-
@log.error("--> verification_type: "+ verification["type"])
|
1116
|
-
@log.error("--> verification_timestamp: "+ verification["timestamp"].to_s)
|
1117
|
-
@log.error("--> validator_id: "+ verification["validator_id"])
|
1118
|
-
@log.error("--> validator_pubkey: "+ validator_pubkey)
|
1119
|
-
@log.error("--> validator_sig: "+ Base64.decode64(verification["validator_sig"]))
|
1120
|
-
end
|
799
|
+
next
|
800
|
+
end
|
1121
801
|
|
1122
|
-
|
1123
|
-
|
802
|
+
# 1b. check field_hash
|
803
|
+
if !document.key?(data_point["field_hash"])
|
804
|
+
if @log.error?
|
805
|
+
@log.error("[check] not a valid data point - field_hash mismatch ("+ data_point["field_hash"] +")")
|
806
|
+
end
|
807
|
+
|
808
|
+
next
|
809
|
+
end
|
810
|
+
|
811
|
+
# 1c. check data_hash
|
812
|
+
data_hash = document[data_point["field_hash"]]
|
813
|
+
if data_hash != data_point["data_hash"]
|
814
|
+
if @log.error?
|
815
|
+
@log.error("[check] not a valid data point - data_hash mismatch ("+ data_hash +")")
|
816
|
+
end
|
817
|
+
|
818
|
+
next
|
819
|
+
end
|
820
|
+
|
821
|
+
# 1d. check data_point_hash
|
822
|
+
checksum_to_hash = data_point["field_hash"] + data_point["data_hash"] + data_point["doc_hash"] + data_point["type"] + data_point["issuer_sig"] + data_point["issuer_id"] + data_point["validator_sig"] + data_point["validator_id"] + data_point["weight"] + data_point["timestamp"]
|
823
|
+
checksum = Digest::SHA512.hexdigest(checksum_to_hash)
|
824
|
+
if checksum != data_point["data_point_hash"]
|
825
|
+
if @log.error?
|
826
|
+
@log.error("[check] not a valid data point - checksum mismatch ("+ checksum +")")
|
827
|
+
end
|
828
|
+
|
829
|
+
next
|
830
|
+
end
|
831
|
+
|
832
|
+
# 2. check verification_hash to be in target_proof's
|
833
|
+
# first element
|
834
|
+
|
835
|
+
reciepts_validated = 0
|
836
|
+
|
837
|
+
data_point["blockchain_reciepts"].each { |reciept|
|
838
|
+
|
839
|
+
if !reciept.key?("target_proof")
|
840
|
+
if @log.error?
|
841
|
+
@log.error("[check] not a valid blockchain reciept - no target_proof")
|
842
|
+
@log.error(reciept)
|
843
|
+
end
|
844
|
+
|
845
|
+
break
|
846
|
+
end
|
847
|
+
|
848
|
+
if reciept["target_proof"].length <= 0
|
849
|
+
if @log.error?
|
850
|
+
@log.error("[check] not a valid blockchain reciept - target_proof length is <= 0")
|
851
|
+
@log.error(reciept)
|
852
|
+
end
|
853
|
+
|
854
|
+
break
|
855
|
+
end
|
856
|
+
|
857
|
+
if reciept["target_proof"][0]["left"] != data_point["data_point_hash"] && reciept["target_proof"][0]["right"] != data_point["data_point_hash"]
|
858
|
+
if @log.error?
|
859
|
+
@log.error("[check] not a valid blockchain reciept - no target element in target_proof.0")
|
860
|
+
@log.error(reciept)
|
861
|
+
end
|
862
|
+
|
863
|
+
break
|
864
|
+
end
|
865
|
+
|
866
|
+
# verification_hash is in tree
|
867
|
+
# and in right position
|
868
|
+
# now,
|
869
|
+
|
870
|
+
# 3. check tree convergence to root hash
|
871
|
+
# and compare this computed root hash
|
872
|
+
# with merkle_tree_root_hash from response
|
873
|
+
|
874
|
+
computed_tree_root_hash = self.build_merkle_tree(reciept["target_proof"], reciept["timestamp"])
|
875
|
+
|
876
|
+
if computed_tree_root_hash == nil
|
877
|
+
if @log.error?
|
878
|
+
@log.error("[check] not a valid blockchain reciept - failed to compute tree root hash")
|
879
|
+
@log.error(reciept)
|
880
|
+
end
|
881
|
+
|
882
|
+
break
|
883
|
+
end
|
884
|
+
if computed_tree_root_hash != reciept["merkle_tree_root_hash"]
|
885
|
+
if @log.error?
|
886
|
+
@log.error("[check] not a valid blockchain reciept - merkle tree root hash mismatch ("+ computed_tree_root_hash +", "+ reciept["merkle_tree_root_hash"] +")")
|
887
|
+
@log.error(reciept)
|
888
|
+
end
|
889
|
+
|
890
|
+
break
|
891
|
+
end
|
892
|
+
|
893
|
+
last_proof_index = reciept["target_proof"].length - 1
|
894
|
+
reciept_stored_last_parent = reciept["target_proof"][last_proof_index]["parent"]
|
895
|
+
if reciept_stored_last_parent != computed_tree_root_hash
|
896
|
+
if @log.error?
|
897
|
+
@log.error("[check] not a valid blockchain reciept - last stored parent != computed_tree_root_hash ("+ reciept_stored_last_parent +", "+ computed_tree_root_hash +")")
|
898
|
+
@log.error(reciept)
|
899
|
+
end
|
900
|
+
|
901
|
+
break
|
902
|
+
end
|
903
|
+
|
904
|
+
# 4. check OP_RETURN in Bitcoin's tx,
|
905
|
+
# compare it to computed root hash of a tree
|
906
|
+
# retrieve some info from tx to verify signature
|
907
|
+
tx = nil
|
908
|
+
|
909
|
+
begin
|
910
|
+
|
911
|
+
tx = blockchainConnection.getTx(reciept["blockchain_txid"])
|
912
|
+
|
913
|
+
rescue => e
|
914
|
+
if @log.error?
|
915
|
+
@log.error("[check] BlockchainConnection.getTx raised exception:")
|
916
|
+
@log.error("#{e.class}, #{e.message}")
|
917
|
+
end
|
918
|
+
|
919
|
+
raise e
|
920
|
+
end
|
921
|
+
|
922
|
+
if tx == nil
|
923
|
+
if @log.error?
|
924
|
+
@log.error("[check] not a valid blockchain reciept - failed to retrieve TX from Blockchain")
|
925
|
+
@log.error(reciept)
|
926
|
+
end
|
927
|
+
|
928
|
+
break
|
929
|
+
end
|
930
|
+
|
931
|
+
if tx["block_hash"] != reciept["blockchain_block_hash"]
|
932
|
+
if @log.error?
|
933
|
+
@log.error("[check] not a valid blockchain reciept - block_hash mismatch")
|
934
|
+
@log.error(tx)
|
935
|
+
@log.error(reciept)
|
936
|
+
end
|
937
|
+
|
938
|
+
break
|
939
|
+
end
|
940
|
+
|
941
|
+
if tx["block_timestamp"] != reciept["blockchain_timestamp"]
|
942
|
+
if @log.error?
|
943
|
+
@log.error("[check] not a valid blockchain reciept - timestamp mismatch")
|
944
|
+
@log.error(tx)
|
945
|
+
@log.error(reciept)
|
946
|
+
end
|
947
|
+
|
948
|
+
break
|
949
|
+
end
|
1124
950
|
|
1125
|
-
|
1126
|
-
|
951
|
+
if tx["op_return"] != computed_tree_root_hash
|
952
|
+
if @log.error?
|
953
|
+
@log.error("[check] not a valid blockchain reciept - op_return mismatch")
|
954
|
+
@log.error(computed_tree_root_hash)
|
955
|
+
@log.error(tx)
|
956
|
+
@log.error(reciept)
|
957
|
+
end
|
958
|
+
|
959
|
+
break
|
960
|
+
end
|
1127
961
|
|
962
|
+
blockchain_txid = reciept["blockchain_txid"];
|
963
|
+
blockchain_block_hash = tx["block_hash"];
|
964
|
+
blockchain_timestamp = tx["block_timestamp"];
|
965
|
+
|
966
|
+
# 5. check tree signature:
|
967
|
+
# a) federative server record in Blockstack (recursive)
|
968
|
+
# b) tree_signature
|
969
|
+
|
970
|
+
# a) federative server record in Blockstack (recursive)
|
971
|
+
begin
|
1128
972
|
|
1129
|
-
|
1130
|
-
|
973
|
+
if !blockstackClient.checkFederativeServer(reciept["federative_server_id"])
|
974
|
+
if @log.error?
|
975
|
+
@log.error("[check] not a valid blockchain reciept - failed to check federative server")
|
976
|
+
@log.error(reciept)
|
1131
977
|
end
|
1132
|
-
validated_verifications[field] = validated_verifications[field] + 1
|
1133
|
-
}
|
1134
978
|
|
1135
|
-
|
1136
|
-
|
1137
|
-
|
1138
|
-
|
1139
|
-
|
979
|
+
break
|
980
|
+
end
|
981
|
+
|
982
|
+
rescue => e
|
983
|
+
if @log.error?
|
984
|
+
@log.error("[check] Blockstack.checkFederativeServer raised exception:")
|
985
|
+
@log.error("#{e.class}, #{e.message}")
|
986
|
+
@log.error(reciept)
|
987
|
+
end
|
988
|
+
|
989
|
+
raise e
|
990
|
+
end
|
991
|
+
|
992
|
+
# b) check tree signature
|
993
|
+
federative_server_pubkey = nil
|
994
|
+
|
995
|
+
begin
|
996
|
+
|
997
|
+
federative_server_pubkey = blockstackClient.getPublicKey(reciept["federative_server_id"])
|
998
|
+
|
999
|
+
rescue => e
|
1000
|
+
if @log.error?
|
1001
|
+
@log.error("[check] Blockstack.getPublicKey raised exception:")
|
1002
|
+
@log.error("#{e.class}, #{e.message}")
|
1003
|
+
@log.error(reciept)
|
1004
|
+
end
|
1005
|
+
|
1006
|
+
raise e
|
1007
|
+
end
|
1008
|
+
|
1009
|
+
if federative_server_pubkey == nil
|
1010
|
+
if @log.error?
|
1011
|
+
@log.error("[check] not a valid blockchain reciept - failed to retrieve public key for federative server '"+ reciept["federative_server_id"] +"'")
|
1012
|
+
@log.error(reciept)
|
1013
|
+
end
|
1014
|
+
|
1015
|
+
break
|
1016
|
+
end
|
1017
|
+
|
1018
|
+
begin
|
1019
|
+
|
1020
|
+
if !signaturesHelper.checkTreeSignature(computed_tree_root_hash, blockchain_txid, blockchain_block_hash, blockchain_timestamp, reciept["federative_server_id"], reciept["federative_server_version"], Base64.decode64(reciept["tree_signature"]), federative_server_pubkey)
|
1021
|
+
if @log.error?
|
1022
|
+
@log.error("[check] not a valid blockchain reciept - failed to verify tree signature")
|
1023
|
+
@log.error(reciept)
|
1024
|
+
@log.error("--> computed_tree_root_hash: #{computed_tree_root_hash}")
|
1025
|
+
@log.error("--> blockchain_txid: #{blockchain_txid}")
|
1026
|
+
@log.error("--> blockchain_block_hash: #{blockchain_block_hash}")
|
1027
|
+
@log.error("--> blockchain_timestamp: #{blockchain_timestamp}")
|
1028
|
+
@log.error("--> federative_server_id: "+ reciept["federative_server_id"])
|
1029
|
+
@log.error("--> federative_server_version: "+ reciept["federative_server_version"])
|
1030
|
+
@log.error("--> tree_signature: "+ Base64.decode64(reciept["tree_signature"]))
|
1031
|
+
@log.error("--> federative_server_pubkey: #{federative_server_pubkey}")
|
1140
1032
|
end
|
1141
1033
|
|
1142
|
-
|
1034
|
+
break
|
1035
|
+
end
|
1036
|
+
|
1037
|
+
rescue => e
|
1038
|
+
if @log.error?
|
1039
|
+
@log.error("[check] Blockstack.checkTreeSignature raised exception:")
|
1040
|
+
@log.error("#{e.class}, #{e.message}")
|
1041
|
+
@log.error(reciept)
|
1042
|
+
@log.error("--> computed_tree_root_hash: #{computed_tree_root_hash}")
|
1043
|
+
@log.error("--> blockchain_txid: #{blockchain_txid}")
|
1044
|
+
@log.error("--> blockchain_block_hash: #{blockchain_block_hash}")
|
1045
|
+
@log.error("--> blockchain_timestamp: #{blockchain_timestamp}")
|
1046
|
+
@log.error("--> federative_server_id: "+ reciept["federative_server_id"])
|
1047
|
+
@log.error("--> federative_server_version: "+ reciept["federative_server_version"])
|
1048
|
+
@log.error("--> tree_signature: "+ Base64.decode64(reciept["tree_signature"]))
|
1049
|
+
@log.error("--> federative_server_pubkey: #{federative_server_pubkey}")
|
1143
1050
|
end
|
1144
|
-
|
1051
|
+
|
1052
|
+
raise e
|
1053
|
+
end
|
1054
|
+
|
1055
|
+
reciepts_validated += 1
|
1145
1056
|
}
|
1146
1057
|
|
1147
|
-
if
|
1148
|
-
@log.
|
1149
|
-
|
1058
|
+
if reciepts_validated != data_point["blockchain_reciepts"].length
|
1059
|
+
if @log.error?
|
1060
|
+
@log.error("[check] not a valid verification - not every reciept were validated")
|
1061
|
+
end
|
1062
|
+
|
1063
|
+
next
|
1150
1064
|
end
|
1151
1065
|
|
1152
|
-
# check
|
1153
|
-
|
1154
|
-
|
1155
|
-
|
1156
|
-
|
1066
|
+
# 6. check verification signatures:
|
1067
|
+
# a) check verificator record in Blockstack (recursive)
|
1068
|
+
# b) check validator record in Blockstack (recursive)
|
1069
|
+
# c) verificator_sig
|
1070
|
+
# d) validtor_sig
|
1071
|
+
|
1072
|
+
# a) check verificator record in Blockstack (recursive)
|
1073
|
+
begin
|
1074
|
+
|
1075
|
+
if !blockstackClient.checkVerificator(data_point["issuer_id"])
|
1076
|
+
if @log.error?
|
1077
|
+
@log.error("[check] not a valid verification - failed to check verificator record")
|
1078
|
+
@log.error("--> verificator_id: "+ data_point["issuer_id"])
|
1157
1079
|
end
|
1080
|
+
|
1081
|
+
next
|
1158
1082
|
end
|
1159
|
-
|
1083
|
+
|
1084
|
+
rescue => e
|
1085
|
+
if @log.error?
|
1086
|
+
@log.error("[check] Blockstack.checkVerificator raised exception:")
|
1087
|
+
@log.error("#{e.class}, #{e.message}")
|
1088
|
+
@log.error("--> verificator_id: "+ data_point["issuer_id"])
|
1089
|
+
end
|
1090
|
+
|
1091
|
+
raise e
|
1092
|
+
end
|
1093
|
+
|
1094
|
+
# b) check validator record in Blockstack (recursive)
|
1095
|
+
begin
|
1096
|
+
|
1097
|
+
if !blockstackClient.checkValidator(data_point["validator_id"])
|
1098
|
+
if @log.error?
|
1099
|
+
@log.error("[check] not a valid verification - failed to check validator record")
|
1100
|
+
@log.error("--> validator_id: "+ data_point["validator_id"])
|
1101
|
+
end
|
1102
|
+
|
1103
|
+
next
|
1104
|
+
end
|
1105
|
+
|
1106
|
+
rescue => e
|
1107
|
+
if @log.error?
|
1108
|
+
@log.error("[check] Blockstack.checkValidator raised exception:")
|
1109
|
+
@log.error("#{e.class}, #{e.message}")
|
1110
|
+
@log.error("--> validator_id: "+ data_point["validator_id"])
|
1111
|
+
end
|
1112
|
+
|
1113
|
+
raise e
|
1114
|
+
end
|
1115
|
+
|
1116
|
+
# c) check verificator's signature
|
1117
|
+
verificator_pubkey = nil
|
1118
|
+
|
1119
|
+
begin
|
1120
|
+
|
1121
|
+
verificator_pubkey = blockstackClient.getPublicKey(data_point["issuer_id"])
|
1122
|
+
|
1123
|
+
rescue => e
|
1124
|
+
if @log.error?
|
1125
|
+
@log.error("[check] Blockstack.getPublicKey raised exception:")
|
1126
|
+
@log.error("#{e.class}, #{e.message}")
|
1127
|
+
@log.error("--> verificator_id: "+ data_point["issuer_id"])
|
1128
|
+
end
|
1129
|
+
|
1130
|
+
raise e
|
1131
|
+
end
|
1132
|
+
|
1133
|
+
if verificator_pubkey == nil
|
1134
|
+
if @log.error?
|
1135
|
+
@log.error("[check] failed to retrieve public key for verificator")
|
1136
|
+
@log.error(document)
|
1137
|
+
@log.error("--> verificator_id: "+ data_point["issuer_id"])
|
1138
|
+
end
|
1139
|
+
|
1140
|
+
next
|
1141
|
+
end
|
1160
1142
|
|
1161
1143
|
if @log.debug?
|
1162
|
-
@log.debug("
|
1163
|
-
@log.debug(
|
1144
|
+
@log.debug("verificator pubkey:")
|
1145
|
+
@log.debug(verificator_pubkey)
|
1164
1146
|
end
|
1165
|
-
end
|
1166
1147
|
|
1167
|
-
|
1148
|
+
begin
|
1168
1149
|
|
1169
|
-
|
1150
|
+
if !signaturesHelper.checkVerificationSignature(data_point["field_hash"], data_point["data_hash"], data_point["doc_hash"], data_point["type"], data_point["weight"], data_point["timestamp"], data_point["issuer_id"], verificator_pubkey, Base64.decode64(data_point["issuer_sig"]))
|
1151
|
+
if @log.error?
|
1152
|
+
@log.error("[check] not a valid verification - failed to check verificator signature")
|
1153
|
+
@log.error("--> field_hash: "+ data_point["field_hash"])
|
1154
|
+
@log.error("--> data_hash: "+ data_point["data_hash"])
|
1155
|
+
@log.error("--> doc_hash: "+ data_point["doc_hash"])
|
1156
|
+
@log.error("--> type: "+ data_point["type"])
|
1157
|
+
@log.error("--> weight: "+ data_point["weight"].to_s)
|
1158
|
+
@log.error("--> timestamp: "+ data_point["timestamp"].to_s)
|
1159
|
+
@log.error("--> verificator_id: "+ data_point["issuer_id"])
|
1160
|
+
@log.error("--> verificator_pubkey: "+ verificator_pubkey)
|
1161
|
+
@log.error("--> verificator_sig: "+ data_point["issuer_sig"])
|
1162
|
+
end
|
1170
1163
|
|
1171
|
-
|
1164
|
+
next
|
1165
|
+
end
|
1172
1166
|
|
1173
|
-
|
1174
|
-
|
1167
|
+
rescue => e
|
1168
|
+
if @log.error?
|
1169
|
+
@log.error("[check] Signatures.checkVerificationSignature raised exception:")
|
1170
|
+
@log.error("#{e.class}, #{e.message}")
|
1171
|
+
@log.error("--> field_hash: "+ data_point["field_hash"])
|
1172
|
+
@log.error("--> data_hash: "+ data_point["data_hash"])
|
1173
|
+
@log.error("--> doc_hash: "+ data_point["doc_hash"])
|
1174
|
+
@log.error("--> type: "+ data_point["type"])
|
1175
|
+
@log.error("--> weight: "+ data_point["weight"].to_s)
|
1176
|
+
@log.error("--> timestamp: "+ data_point["timestamp"].to_s)
|
1177
|
+
@log.error("--> verificator_id: "+ data_point["issuer_id"])
|
1178
|
+
@log.error("--> verificator_pubkey: "+ verificator_pubkey)
|
1179
|
+
@log.error("--> verificator_sig: "+ data_point["issuer_sig"])
|
1180
|
+
end
|
1175
1181
|
|
1176
|
-
|
1182
|
+
raise e
|
1183
|
+
end
|
1177
1184
|
|
1178
|
-
|
1179
|
-
|
1185
|
+
# d) check validator's signature
|
1186
|
+
validator_pubkey = nil
|
1187
|
+
|
1188
|
+
begin
|
1189
|
+
|
1190
|
+
validator_pubkey = blockstackClient.getPublicKey(data_point["validator_id"])
|
1191
|
+
|
1192
|
+
rescue => e
|
1193
|
+
if @log.error?
|
1194
|
+
@log.error("[check] Blockstack.getPublicKey raised exception:")
|
1195
|
+
@log.error("#{e.class}, #{e.message}")
|
1196
|
+
@log.error("--> validator_id: "+ data_point["validator_id"])
|
1180
1197
|
end
|
1181
1198
|
|
1182
|
-
|
1183
|
-
"status" => "error",
|
1184
|
-
"possible_mistakes" => possible_mistakes_output,
|
1185
|
-
"validated" => validated_verifications,
|
1186
|
-
"reason" => res["error_reason_code"]
|
1187
|
-
}
|
1199
|
+
raise e
|
1188
1200
|
end
|
1189
1201
|
|
1190
|
-
|
1191
|
-
|
1192
|
-
|
1193
|
-
|
1202
|
+
if validator_pubkey == nil
|
1203
|
+
if @log.error?
|
1204
|
+
@log.error("[check] failed to retrieve pubic key for validator")
|
1205
|
+
@log.error("--> validator_id: "+ data_point["validator_id"])
|
1206
|
+
end
|
1194
1207
|
|
1195
|
-
|
1196
|
-
|
1197
|
-
return validated_verifications
|
1208
|
+
next
|
1209
|
+
end
|
1198
1210
|
|
1199
|
-
|
1211
|
+
if @log.debug?
|
1212
|
+
@log.debug("validator pubkey:")
|
1213
|
+
@log.debug(validator_pubkey)
|
1214
|
+
end
|
1215
|
+
|
1216
|
+
begin
|
1217
|
+
|
1218
|
+
if !signaturesHelper.checkVerificationSignature(data_point["field_hash"], data_point["data_hash"], data_point["doc_hash"], data_point["type"], data_point["weight"], data_point["timestamp"], data_point["validator_id"], validator_pubkey, Base64.decode64(data_point["validator_sig"]))
|
1219
|
+
if @log.error?
|
1220
|
+
@log.error("[check] not a valid verification - failed to check validator signature")
|
1221
|
+
@log.error("--> field_hash: "+ data_point["field_hash"])
|
1222
|
+
@log.error("--> data_hash: "+ data_point["data_hash"])
|
1223
|
+
@log.error("--> doc_hash: "+ data_point["doc_hash"])
|
1224
|
+
@log.error("--> type: "+ data_point["type"])
|
1225
|
+
@log.error("--> weight: "+ data_point["weight"].to_s)
|
1226
|
+
@log.error("--> timestamp: "+ data_point["timestamp"].to_s)
|
1227
|
+
@log.error("--> validator_id: "+ data_point["validator_id"])
|
1228
|
+
@log.error("--> validator_pubkey: "+ validator_pubkey)
|
1229
|
+
@log.error("--> validator_sig: "+ Base64.encode64(data_point["validator_sig"]))
|
1230
|
+
end
|
1231
|
+
|
1232
|
+
next
|
1233
|
+
end
|
1234
|
+
|
1235
|
+
rescue => e
|
1236
|
+
if @log.error?
|
1237
|
+
@log.error("[check] Signatures.checkVerificationSignature raised exception:")
|
1238
|
+
@log.error("#{e.class}, #{e.message}")
|
1239
|
+
@log.error("--> field_hash: "+ data_point["field_hash"])
|
1240
|
+
@log.error("--> data_hash: "+ data_point["data_hash"])
|
1241
|
+
@log.error("--> doc_hash: "+ data_point["doc_hash"])
|
1242
|
+
@log.error("--> type: "+ data_point["type"])
|
1243
|
+
@log.error("--> weight: "+ data_point["weight"].to_s)
|
1244
|
+
@log.error("--> timestamp: "+ data_point["timestamp"].to_s)
|
1245
|
+
@log.error("--> validator_id: "+ data_point["validator_id"])
|
1246
|
+
@log.error("--> validator_pubkey: "+ validator_pubkey)
|
1247
|
+
@log.error("--> validator_sig: "+ Base64.encode64(data_point["validator_sig"]))
|
1248
|
+
end
|
1249
|
+
|
1250
|
+
raise e
|
1251
|
+
end
|
1252
|
+
|
1253
|
+
# 7. timestamps checking
|
1254
|
+
# TODO
|
1255
|
+
|
1256
|
+
if !output.key?(data_point["doc_hash"])
|
1257
|
+
output[data_point["doc_hash"]] = {}
|
1258
|
+
end
|
1259
|
+
if !output[data_point["doc_hash"]].key?(data_point["field_hash"])
|
1260
|
+
output[data_point["doc_hash"]][data_point["field_hash"]] = 0
|
1261
|
+
end
|
1262
|
+
|
1263
|
+
output[data_point["doc_hash"]][data_point["field_hash"]] += 1
|
1264
|
+
}
|
1265
|
+
|
1266
|
+
return output
|
1200
1267
|
end
|
1201
1268
|
|
1202
1269
|
def self.generateBlockstackCommand(config)
|