@prosopo/datasets 3.1.54 → 3.1.55
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.
- package/.turbo/turbo-build$colon$cjs.log +15 -13
- package/.turbo/turbo-build$colon$tsc.log +11 -11
- package/.turbo/turbo-build.log +17 -14
- package/CHANGELOG.md +14 -0
- package/dist/_virtual/_rolldown/runtime.js +3 -0
- package/dist/captcha/captcha.js +171 -168
- package/dist/captcha/dataset.js +64 -82
- package/dist/captcha/index.js +2 -24
- package/dist/captcha/merkle.js +93 -123
- package/dist/captcha/util.js +14 -20
- package/dist/cjs/captcha/captcha.cjs +173 -158
- package/dist/cjs/captcha/dataset.cjs +64 -79
- package/dist/cjs/captcha/index.cjs +25 -27
- package/dist/cjs/captcha/merkle.cjs +95 -124
- package/dist/cjs/captcha/util.cjs +14 -20
- package/dist/cjs/index.cjs +28 -30
- package/dist/cjs/tests/mocks/data/captchas.cjs +1026 -1040
- package/dist/index.js +4 -28
- package/dist/tests/mocks/data/captchas.js +1027 -1042
- package/package.json +9 -9
|
@@ -1,185 +1,200 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
const require_util = require("./util.cjs");
|
|
2
|
+
let _polkadot_util = require("@polkadot/util");
|
|
3
|
+
let _prosopo_common = require("@prosopo/common");
|
|
4
|
+
let _prosopo_types = require("@prosopo/types");
|
|
5
|
+
let _prosopo_util = require("@prosopo/util");
|
|
6
|
+
let _prosopo_util_crypto = require("@prosopo/util-crypto");
|
|
7
|
+
//#region src/captcha/captcha.ts
|
|
8
|
+
var NO_SOLUTION_VALUE = "NO_SOLUTION";
|
|
9
|
+
/**
|
|
10
|
+
* Parse a dataset
|
|
11
|
+
* @return {JSON} captcha dataset, stored in JSON
|
|
12
|
+
* @param datasetJSON
|
|
13
|
+
*/
|
|
10
14
|
function parseCaptchaDataset(datasetJSON) {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
} catch (err) {
|
|
32
|
-
throw new common.ProsopoDatasetError("DATASET.DATASET_PARSE_ERROR", {
|
|
33
|
-
context: { error: err }
|
|
34
|
-
});
|
|
35
|
-
}
|
|
15
|
+
try {
|
|
16
|
+
const result = _prosopo_types.DatasetWithNumericSolutionSchema.parse(datasetJSON);
|
|
17
|
+
const result2 = {
|
|
18
|
+
format: result.format,
|
|
19
|
+
captchas: result.captchas.map((captcha) => {
|
|
20
|
+
return {
|
|
21
|
+
...captcha,
|
|
22
|
+
solution: captcha.solution ? matchItemsToSolutions(captcha.solution, captcha.items) : [],
|
|
23
|
+
unlabelled: captcha.unlabelled ? matchItemsToSolutions(captcha.unlabelled, captcha.items) : []
|
|
24
|
+
};
|
|
25
|
+
})
|
|
26
|
+
};
|
|
27
|
+
if (result.datasetId !== void 0) result2.datasetId = result.datasetId;
|
|
28
|
+
if (result.contentTree !== void 0) result2.contentTree = result.contentTree;
|
|
29
|
+
if (result.datasetContentId !== void 0) result2.datasetContentId = result.datasetContentId;
|
|
30
|
+
if (result.solutionTree !== void 0) result2.solutionTree = result.solutionTree;
|
|
31
|
+
return result2;
|
|
32
|
+
} catch (err) {
|
|
33
|
+
throw new _prosopo_common.ProsopoDatasetError("DATASET.DATASET_PARSE_ERROR", { context: { error: err } });
|
|
34
|
+
}
|
|
36
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* Make sure captcha solutions are in the correct format
|
|
38
|
+
* @param {JSON} captchaJSON captcha solutions received from the api
|
|
39
|
+
* @return {CaptchaSolution[]} an array of parsed and sorted captcha solutions
|
|
40
|
+
*/
|
|
37
41
|
function parseAndSortCaptchaSolutions(captchaJSON) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
});
|
|
47
|
-
}
|
|
42
|
+
try {
|
|
43
|
+
return _prosopo_types.CaptchaSolutionArraySchema.parse(captchaJSON).map((captcha) => ({
|
|
44
|
+
...captcha,
|
|
45
|
+
solution: captcha.solution.sort()
|
|
46
|
+
}));
|
|
47
|
+
} catch (err) {
|
|
48
|
+
throw new _prosopo_common.ProsopoDatasetError("DATASET.SOLUTION_PARSE_ERROR", { context: { error: err } });
|
|
49
|
+
}
|
|
48
50
|
}
|
|
49
51
|
function captchaSort(a, b) {
|
|
50
|
-
|
|
52
|
+
return a.captchaId.localeCompare(b.captchaId);
|
|
51
53
|
}
|
|
52
54
|
function sortAndComputeHashes(received, stored) {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
},
|
|
69
|
-
true,
|
|
70
|
-
true,
|
|
71
|
-
false
|
|
72
|
-
),
|
|
73
|
-
captchaId
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
);
|
|
55
|
+
received.sort(captchaSort);
|
|
56
|
+
stored.sort(captchaSort);
|
|
57
|
+
return stored.map(({ salt, items = [], target = "", captchaId, solved }, index) => {
|
|
58
|
+
const item = (0, _prosopo_util.at)(received, index);
|
|
59
|
+
if (captchaId !== item.captchaId) throw new _prosopo_common.ProsopoEnvError("CAPTCHA.ID_MISMATCH");
|
|
60
|
+
return {
|
|
61
|
+
hash: computeCaptchaHash({
|
|
62
|
+
solution: solved ? item.solution : [],
|
|
63
|
+
salt,
|
|
64
|
+
items,
|
|
65
|
+
target
|
|
66
|
+
}, true, true, false),
|
|
67
|
+
captchaId
|
|
68
|
+
};
|
|
69
|
+
});
|
|
77
70
|
}
|
|
71
|
+
/**
|
|
72
|
+
* Take an array of CaptchaSolutions and Captchas and check if the solutions are the same for each pair
|
|
73
|
+
* @param {CaptchaSolution[]} received
|
|
74
|
+
* @param solutions
|
|
75
|
+
* @param totalImages
|
|
76
|
+
* @param {number} threshold the percentage of captchas that must be correct to return true
|
|
77
|
+
* @return {boolean}
|
|
78
|
+
*/
|
|
78
79
|
function compareCaptchaSolutions(received, solutions, totalImages, threshold) {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
}
|
|
92
|
-
return received.every((captcha, index) => {
|
|
93
|
-
const sortedReceivedSolution = captcha.solution.sort();
|
|
94
|
-
const targetSolution = solutions[index]?.solution.sort();
|
|
95
|
-
if (!targetSolution) {
|
|
96
|
-
return false;
|
|
97
|
-
}
|
|
98
|
-
const incorrectCount = sortedReceivedSolution.filter(
|
|
99
|
-
(solution) => !targetSolution.includes(solution)
|
|
100
|
-
).length;
|
|
101
|
-
const missingCount = targetSolution.filter(
|
|
102
|
-
(solution) => !sortedReceivedSolution.includes(solution)
|
|
103
|
-
).length;
|
|
104
|
-
const totalIncorrect = incorrectCount + missingCount;
|
|
105
|
-
const percentageCorrect = 1 - totalIncorrect / totalImages;
|
|
106
|
-
return percentageCorrect >= threshold;
|
|
107
|
-
});
|
|
80
|
+
received.sort(captchaSort);
|
|
81
|
+
solutions.sort(captchaSort);
|
|
82
|
+
if (received.length !== solutions.length) return false;
|
|
83
|
+
if (received.length && solutions.length && received.length === solutions.length) {
|
|
84
|
+
if (received.some((captcha, index) => solutions[index] && captcha.captchaId !== solutions[index].captchaId)) return false;
|
|
85
|
+
}
|
|
86
|
+
return received.every((captcha, index) => {
|
|
87
|
+
const sortedReceivedSolution = captcha.solution.sort();
|
|
88
|
+
const targetSolution = solutions[index]?.solution.sort();
|
|
89
|
+
if (!targetSolution) return false;
|
|
90
|
+
return 1 - (sortedReceivedSolution.filter((solution) => !targetSolution.includes(solution)).length + targetSolution.filter((solution) => !sortedReceivedSolution.includes(solution)).length) / totalImages >= threshold;
|
|
91
|
+
});
|
|
108
92
|
}
|
|
93
|
+
/**
|
|
94
|
+
* Compute the hash of various types of captcha
|
|
95
|
+
* @param {Captcha} captcha
|
|
96
|
+
* @param {boolean} includeSolution
|
|
97
|
+
* @param {boolean} includeSalt
|
|
98
|
+
* @param {boolean} sortItemHashes
|
|
99
|
+
* @return {string} the hex string hash
|
|
100
|
+
*/
|
|
109
101
|
function computeCaptchaHash(captcha, includeSolution, includeSalt, sortItemHashes) {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
includeSalt ? captcha.salt : "",
|
|
128
|
-
sortItemHashes ? itemHashes.sort() : itemHashes
|
|
129
|
-
]);
|
|
130
|
-
} catch (err) {
|
|
131
|
-
throw new common.ProsopoDatasetError("DATASET.HASH_ERROR", {
|
|
132
|
-
context: { error: err }
|
|
133
|
-
});
|
|
134
|
-
}
|
|
102
|
+
try {
|
|
103
|
+
const itemHashes = captcha.items.map((item, index) => {
|
|
104
|
+
if (item.hash) return item.hash;
|
|
105
|
+
throw new _prosopo_common.ProsopoDatasetError("CAPTCHA.MISSING_ITEM_HASH", { context: {
|
|
106
|
+
computeCaptchaHashName: computeCaptchaHash.name,
|
|
107
|
+
index
|
|
108
|
+
} });
|
|
109
|
+
});
|
|
110
|
+
return (0, _prosopo_util_crypto.hexHashArray)([
|
|
111
|
+
captcha.target,
|
|
112
|
+
...includeSolution ? getSolutionValueToHash(captcha.solution) : [],
|
|
113
|
+
includeSalt ? captcha.salt : "",
|
|
114
|
+
sortItemHashes ? itemHashes.sort() : itemHashes
|
|
115
|
+
]);
|
|
116
|
+
} catch (err) {
|
|
117
|
+
throw new _prosopo_common.ProsopoDatasetError("DATASET.HASH_ERROR", { context: { error: err } });
|
|
118
|
+
}
|
|
135
119
|
}
|
|
120
|
+
/** Return the sorted solution value or ['NO_SOLUTION'] if there is no solution. Ensures that an empty array is a valid
|
|
121
|
+
* solution
|
|
122
|
+
* @param solution
|
|
123
|
+
*/
|
|
136
124
|
function getSolutionValueToHash(solution) {
|
|
137
|
-
|
|
125
|
+
return solution !== void 0 ? solution.sort() : [NO_SOLUTION_VALUE];
|
|
138
126
|
}
|
|
127
|
+
/** Compute the hash of a captcha item, downloading the image if necessary
|
|
128
|
+
* @param {Item} item
|
|
129
|
+
* @return {Promise<HashedItem>} the hex string hash of the item
|
|
130
|
+
*/
|
|
139
131
|
async function computeItemHash(item) {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
132
|
+
if (item.type === "text") return {
|
|
133
|
+
...item,
|
|
134
|
+
hash: (0, _prosopo_util_crypto.hexHash)(item.data)
|
|
135
|
+
};
|
|
136
|
+
if (item.type === "image") return {
|
|
137
|
+
...item,
|
|
138
|
+
hash: (0, _prosopo_util_crypto.hexHash)(await require_util.downloadImage(item.data))
|
|
139
|
+
};
|
|
140
|
+
throw new _prosopo_common.ProsopoDatasetError("CAPTCHA.INVALID_ITEM_FORMAT");
|
|
147
141
|
}
|
|
142
|
+
/**
|
|
143
|
+
* Converts an indexed captcha solution to a hashed captcha solution or simply returns the hash if it is already hashed
|
|
144
|
+
* @return {HashedSolution[]}
|
|
145
|
+
* @param {RawSolution[] | HashedSolution[]} solutions
|
|
146
|
+
* @param {Item[]} items
|
|
147
|
+
*/
|
|
148
148
|
function matchItemsToSolutions(solutions, items) {
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
}
|
|
159
|
-
if (typeof solution === "number") {
|
|
160
|
-
const item = util.at(items, solution);
|
|
161
|
-
return item.hash;
|
|
162
|
-
}
|
|
163
|
-
throw new common.ProsopoDatasetError("CAPTCHA.INVALID_SOLUTION_TYPE");
|
|
164
|
-
});
|
|
149
|
+
if (!items) return [];
|
|
150
|
+
return solutions.map((solution) => {
|
|
151
|
+
if (typeof solution === "string" && (0, _polkadot_util.isHex)(solution)) {
|
|
152
|
+
if (!items?.some((item) => item.hash === solution)) throw new _prosopo_common.ProsopoDatasetError("CAPTCHA.INVALID_ITEM_HASH");
|
|
153
|
+
return solution;
|
|
154
|
+
}
|
|
155
|
+
if (typeof solution === "number") return (0, _prosopo_util.at)(items, solution).hash;
|
|
156
|
+
throw new _prosopo_common.ProsopoDatasetError("CAPTCHA.INVALID_SOLUTION_TYPE");
|
|
157
|
+
});
|
|
165
158
|
}
|
|
159
|
+
/**
|
|
160
|
+
* Create a unique solution commitment
|
|
161
|
+
* @param {CaptchaSolution} captcha
|
|
162
|
+
* @return {string} the hex string hash
|
|
163
|
+
*/
|
|
166
164
|
function computeCaptchaSolutionHash(captcha) {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
165
|
+
return (0, _prosopo_util_crypto.hexHashArray)([
|
|
166
|
+
captcha.captchaId,
|
|
167
|
+
captcha.captchaContentId,
|
|
168
|
+
[...captcha.solution].sort(),
|
|
169
|
+
captcha.salt
|
|
170
|
+
]);
|
|
173
171
|
}
|
|
172
|
+
/**
|
|
173
|
+
* Compute hash for an array of captcha ids, userAccount, and salt, which serves as the identifier for a pending request
|
|
174
|
+
* @param {string[]} captchaIds
|
|
175
|
+
* @param {string} userAccount
|
|
176
|
+
* @param {string} salt
|
|
177
|
+
* @return {string}
|
|
178
|
+
*/
|
|
174
179
|
function computePendingRequestHash(captchaIds, userAccount, salt) {
|
|
175
|
-
|
|
180
|
+
return (0, _prosopo_util_crypto.hexHashArray)([
|
|
181
|
+
...captchaIds.sort(),
|
|
182
|
+
userAccount,
|
|
183
|
+
salt
|
|
184
|
+
]);
|
|
176
185
|
}
|
|
186
|
+
/**
|
|
187
|
+
* Parse the image items in a captcha and pass back a URI if they exist
|
|
188
|
+
* @param {Item} item
|
|
189
|
+
* @param {AssetsResolver} assetsResolver
|
|
190
|
+
*/
|
|
177
191
|
function parseCaptchaAssets(item, assetsResolver) {
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
192
|
+
return {
|
|
193
|
+
...item,
|
|
194
|
+
data: assetsResolver?.resolveAsset(item.data).getURL() || item.data
|
|
195
|
+
};
|
|
182
196
|
}
|
|
197
|
+
//#endregion
|
|
183
198
|
exports.NO_SOLUTION_VALUE = NO_SOLUTION_VALUE;
|
|
184
199
|
exports.captchaSort = captchaSort;
|
|
185
200
|
exports.compareCaptchaSolutions = compareCaptchaSolutions;
|
|
@@ -1,92 +1,77 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const merkle = require("./merkle.cjs");
|
|
8
|
-
const logger = logger$1.getLogger("info", "datasets:captcha");
|
|
1
|
+
const require_captcha = require("./captcha.cjs");
|
|
2
|
+
const require_merkle = require("./merkle.cjs");
|
|
3
|
+
let _prosopo_common = require("@prosopo/common");
|
|
4
|
+
let _prosopo_util = require("@prosopo/util");
|
|
5
|
+
//#region src/captcha/dataset.ts
|
|
6
|
+
var logger = (0, require("@prosopo/logger").getLogger)("info", "datasets:captcha");
|
|
9
7
|
async function hashDatasetItems(datasetRaw) {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
};
|
|
18
|
-
});
|
|
8
|
+
return datasetRaw.captchas.map(async (captcha) => {
|
|
9
|
+
const items = await Promise.all(captcha.items.map(async (item) => require_captcha.computeItemHash(item)));
|
|
10
|
+
return {
|
|
11
|
+
...captcha,
|
|
12
|
+
items
|
|
13
|
+
};
|
|
14
|
+
});
|
|
19
15
|
}
|
|
16
|
+
/**
|
|
17
|
+
* Take a dataset and hash all the items, making sure that the existing captchaIds and item hashes are correct
|
|
18
|
+
* @param datasetOriginal
|
|
19
|
+
*/
|
|
20
20
|
async function validateDatasetContent(datasetOriginal) {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
if (captchaRaw) {
|
|
32
|
-
return captcha2.items.every(
|
|
33
|
-
(item, index) => item.hash === util.at(captchaRaw.items, index).hash
|
|
34
|
-
);
|
|
35
|
-
}
|
|
36
|
-
return false;
|
|
37
|
-
});
|
|
38
|
-
return hashes.every((hash) => hash);
|
|
21
|
+
const captchaPromises = await hashDatasetItems(datasetOriginal);
|
|
22
|
+
const captchas = await Promise.all(captchaPromises);
|
|
23
|
+
return {
|
|
24
|
+
...datasetOriginal,
|
|
25
|
+
captchas
|
|
26
|
+
}.captchas.map((captcha) => {
|
|
27
|
+
const captchaRaw = datasetOriginal.captchas.find((captchaRaw) => "captchaId" in captchaRaw ? captchaRaw.captchaId === captcha.captchaId : false);
|
|
28
|
+
if (captchaRaw) return captcha.items.every((item, index) => item.hash === (0, _prosopo_util.at)(captchaRaw.items, index).hash);
|
|
29
|
+
return false;
|
|
30
|
+
}).every((hash) => hash);
|
|
39
31
|
}
|
|
40
32
|
async function buildDataset(datasetRaw) {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
dataset.datasetContentId = contentTree.root?.hash;
|
|
59
|
-
return dataset;
|
|
33
|
+
logger.debug(() => ({ msg: "Adding solution hashes to dataset" }));
|
|
34
|
+
const dataset = await addSolutionHashesToDataset(datasetRaw);
|
|
35
|
+
logger.debug(() => ({ msg: "Building dataset merkle trees" }));
|
|
36
|
+
const contentTree = await buildCaptchaTree(dataset, false, false, true);
|
|
37
|
+
const solutionTree = await buildCaptchaTree(dataset, true, true, false);
|
|
38
|
+
dataset.captchas = dataset.captchas.map((captcha, index) => ({
|
|
39
|
+
...captcha,
|
|
40
|
+
captchaId: (0, _prosopo_util.at)(solutionTree.leaves, index).hash,
|
|
41
|
+
captchaContentId: (0, _prosopo_util.at)(contentTree.leaves, index).hash,
|
|
42
|
+
datasetId: solutionTree.root?.hash,
|
|
43
|
+
datasetContentId: contentTree.root?.hash
|
|
44
|
+
}));
|
|
45
|
+
dataset.solutionTree = solutionTree.layers;
|
|
46
|
+
dataset.contentTree = contentTree.layers;
|
|
47
|
+
dataset.datasetId = solutionTree.root?.hash;
|
|
48
|
+
dataset.datasetContentId = contentTree.root?.hash;
|
|
49
|
+
return dataset;
|
|
60
50
|
}
|
|
61
51
|
async function buildCaptchaTree(dataset, includeSolution, includeSalt, sortItemHashes) {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
} catch (err) {
|
|
71
|
-
throw new common.ProsopoEnvError("DATASET.HASH_ERROR");
|
|
72
|
-
}
|
|
52
|
+
try {
|
|
53
|
+
const tree = new require_merkle.CaptchaMerkleTree();
|
|
54
|
+
const captchaHashes = { ...dataset }.captchas.map((captcha) => require_captcha.computeCaptchaHash(captcha, includeSolution, includeSalt, sortItemHashes));
|
|
55
|
+
tree.build(captchaHashes);
|
|
56
|
+
return tree;
|
|
57
|
+
} catch (err) {
|
|
58
|
+
throw new _prosopo_common.ProsopoEnvError("DATASET.HASH_ERROR");
|
|
59
|
+
}
|
|
73
60
|
}
|
|
74
61
|
function addSolutionHashesToDataset(datasetRaw) {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
...datasetRaw,
|
|
87
|
-
captchas
|
|
88
|
-
};
|
|
62
|
+
const captchas = datasetRaw.captchas.map((captcha) => {
|
|
63
|
+
return {
|
|
64
|
+
...captcha,
|
|
65
|
+
items: captcha.items,
|
|
66
|
+
...captcha.solution !== void 0 && { solution: require_captcha.matchItemsToSolutions(captcha.solution, captcha.items) }
|
|
67
|
+
};
|
|
68
|
+
});
|
|
69
|
+
return {
|
|
70
|
+
...datasetRaw,
|
|
71
|
+
captchas
|
|
72
|
+
};
|
|
89
73
|
}
|
|
74
|
+
//#endregion
|
|
90
75
|
exports.addSolutionHashesToDataset = addSolutionHashesToDataset;
|
|
91
76
|
exports.buildCaptchaTree = buildCaptchaTree;
|
|
92
77
|
exports.buildDataset = buildDataset;
|
|
@@ -1,27 +1,25 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
exports.
|
|
8
|
-
exports.
|
|
9
|
-
exports.
|
|
10
|
-
exports.
|
|
11
|
-
exports.
|
|
12
|
-
exports.
|
|
13
|
-
exports.
|
|
14
|
-
exports.
|
|
15
|
-
exports.
|
|
16
|
-
exports.
|
|
17
|
-
exports.
|
|
18
|
-
exports.
|
|
19
|
-
exports.
|
|
20
|
-
exports.
|
|
21
|
-
exports.
|
|
22
|
-
exports.
|
|
23
|
-
exports.
|
|
24
|
-
exports.
|
|
25
|
-
exports.
|
|
26
|
-
exports.hashDatasetItems = dataset.hashDatasetItems;
|
|
27
|
-
exports.validateDatasetContent = dataset.validateDatasetContent;
|
|
1
|
+
const require_util = require("./util.cjs");
|
|
2
|
+
const require_captcha = require("./captcha.cjs");
|
|
3
|
+
const require_merkle = require("./merkle.cjs");
|
|
4
|
+
const require_dataset = require("./dataset.cjs");
|
|
5
|
+
exports.CaptchaMerkleTree = require_merkle.CaptchaMerkleTree;
|
|
6
|
+
exports.NO_SOLUTION_VALUE = require_captcha.NO_SOLUTION_VALUE;
|
|
7
|
+
exports.addSolutionHashesToDataset = require_dataset.addSolutionHashesToDataset;
|
|
8
|
+
exports.buildCaptchaTree = require_dataset.buildCaptchaTree;
|
|
9
|
+
exports.buildDataset = require_dataset.buildDataset;
|
|
10
|
+
exports.captchaSort = require_captcha.captchaSort;
|
|
11
|
+
exports.compareCaptchaSolutions = require_captcha.compareCaptchaSolutions;
|
|
12
|
+
exports.computeCaptchaHash = require_captcha.computeCaptchaHash;
|
|
13
|
+
exports.computeCaptchaSolutionHash = require_captcha.computeCaptchaSolutionHash;
|
|
14
|
+
exports.computeItemHash = require_captcha.computeItemHash;
|
|
15
|
+
exports.computePendingRequestHash = require_captcha.computePendingRequestHash;
|
|
16
|
+
exports.downloadImage = require_util.downloadImage;
|
|
17
|
+
exports.getSolutionValueToHash = require_captcha.getSolutionValueToHash;
|
|
18
|
+
exports.hashDatasetItems = require_dataset.hashDatasetItems;
|
|
19
|
+
exports.matchItemsToSolutions = require_captcha.matchItemsToSolutions;
|
|
20
|
+
exports.parseAndSortCaptchaSolutions = require_captcha.parseAndSortCaptchaSolutions;
|
|
21
|
+
exports.parseCaptchaAssets = require_captcha.parseCaptchaAssets;
|
|
22
|
+
exports.parseCaptchaDataset = require_captcha.parseCaptchaDataset;
|
|
23
|
+
exports.sortAndComputeHashes = require_captcha.sortAndComputeHashes;
|
|
24
|
+
exports.validateDatasetContent = require_dataset.validateDatasetContent;
|
|
25
|
+
exports.verifyProof = require_merkle.verifyProof;
|