@prosopo/datasets 1.0.2 → 2.0.0
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/dist/captcha/captcha.d.ts +3 -3
- package/dist/captcha/captcha.d.ts.map +1 -1
- package/dist/captcha/captcha.js +49 -37
- package/dist/captcha/captcha.js.map +1 -1
- package/dist/captcha/dataset.d.ts +2 -2
- package/dist/captcha/dataset.d.ts.map +1 -1
- package/dist/captcha/dataset.js +15 -13
- package/dist/captcha/dataset.js.map +1 -1
- package/dist/captcha/index.d.ts +4 -4
- package/dist/captcha/index.d.ts.map +1 -1
- package/dist/captcha/index.js +4 -4
- package/dist/captcha/index.js.map +1 -1
- package/dist/captcha/merkle.d.ts +2 -1
- package/dist/captcha/merkle.d.ts.map +1 -1
- package/dist/captcha/merkle.js +22 -5
- package/dist/captcha/merkle.js.map +1 -1
- package/dist/captcha/util.d.ts.map +1 -1
- package/dist/captcha/util.js +9 -4
- package/dist/captcha/util.js.map +1 -1
- package/dist/cjs/captcha/captcha.cjs +56 -42
- package/dist/cjs/captcha/dataset.cjs +14 -9
- package/dist/cjs/captcha/merkle.cjs +22 -3
- package/dist/cjs/captcha/util.cjs +7 -2
- package/dist/cjs/tests/mocks/data/captchas.cjs +6 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/tests/captcha.test.js +149 -138
- package/dist/tests/captcha.test.js.map +1 -1
- package/dist/tests/dataset.test.js +53 -51
- package/dist/tests/dataset.test.js.map +1 -1
- package/dist/tests/merkle.test.js +86 -51
- package/dist/tests/merkle.test.js.map +1 -1
- package/dist/tests/mocks/data/captchas.d.ts +1 -1
- package/dist/tests/mocks/data/captchas.d.ts.map +1 -1
- package/dist/tests/mocks/data/captchas.js +608 -606
- package/dist/tests/mocks/data/captchas.js.map +1 -1
- package/dist/tests/mocks/data/captchas1.json +108 -27
- package/dist/tests/mocks/data/captchas2.json +144 -36
- package/dist/tests/mocks/data/captchas3.json +108 -27
- package/dist/tests/mocks/data/captchas4.json +108 -27
- package/package.json +66 -76
- package/vite.cjs.config.ts +3 -3
- package/vite.test.config.ts +12 -12
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const
|
|
3
|
+
const util$2 = require("@polkadot/util");
|
|
4
4
|
const common = require("@prosopo/common");
|
|
5
|
+
const types = require("@prosopo/types");
|
|
5
6
|
const util = require("@prosopo/util");
|
|
6
7
|
const util$1 = require("./util.cjs");
|
|
7
|
-
const util$2 = require("@polkadot/util");
|
|
8
8
|
const NO_SOLUTION_VALUE = "NO_SOLUTION";
|
|
9
9
|
function parseCaptchaDataset(datasetJSON) {
|
|
10
10
|
try {
|
|
@@ -19,8 +19,7 @@ function parseCaptchaDataset(datasetJSON) {
|
|
|
19
19
|
};
|
|
20
20
|
})
|
|
21
21
|
};
|
|
22
|
-
if (result.datasetId !== void 0)
|
|
23
|
-
result2.datasetId = result.datasetId;
|
|
22
|
+
if (result.datasetId !== void 0) result2.datasetId = result.datasetId;
|
|
24
23
|
if (result.contentTree !== void 0)
|
|
25
24
|
result2.contentTree = result.contentTree;
|
|
26
25
|
if (result.datasetContentId !== void 0)
|
|
@@ -29,7 +28,9 @@ function parseCaptchaDataset(datasetJSON) {
|
|
|
29
28
|
result2.solutionTree = result.solutionTree;
|
|
30
29
|
return result2;
|
|
31
30
|
} catch (err) {
|
|
32
|
-
throw new common.ProsopoDatasetError("DATASET.DATASET_PARSE_ERROR", {
|
|
31
|
+
throw new common.ProsopoDatasetError("DATASET.DATASET_PARSE_ERROR", {
|
|
32
|
+
context: { error: err }
|
|
33
|
+
});
|
|
33
34
|
}
|
|
34
35
|
}
|
|
35
36
|
function parseAndSortCaptchaSolutions(captchaJSON) {
|
|
@@ -39,7 +40,9 @@ function parseAndSortCaptchaSolutions(captchaJSON) {
|
|
|
39
40
|
solution: captcha.solution.sort()
|
|
40
41
|
}));
|
|
41
42
|
} catch (err) {
|
|
42
|
-
throw new common.ProsopoDatasetError("DATASET.SOLUTION_PARSE_ERROR", {
|
|
43
|
+
throw new common.ProsopoDatasetError("DATASET.SOLUTION_PARSE_ERROR", {
|
|
44
|
+
context: { error: err }
|
|
45
|
+
});
|
|
43
46
|
}
|
|
44
47
|
}
|
|
45
48
|
function captchaSort(a, b) {
|
|
@@ -48,26 +51,28 @@ function captchaSort(a, b) {
|
|
|
48
51
|
function sortAndComputeHashes(received, stored) {
|
|
49
52
|
received.sort(captchaSort);
|
|
50
53
|
stored.sort(captchaSort);
|
|
51
|
-
return stored.map(
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
54
|
+
return stored.map(
|
|
55
|
+
({ salt, items = [], target = "", captchaId, solved }, index) => {
|
|
56
|
+
const item = util.at(received, index);
|
|
57
|
+
if (captchaId !== item.captchaId) {
|
|
58
|
+
throw new common.ProsopoEnvError("CAPTCHA.ID_MISMATCH");
|
|
59
|
+
}
|
|
60
|
+
return {
|
|
61
|
+
hash: computeCaptchaHash(
|
|
62
|
+
{
|
|
63
|
+
solution: solved ? item.solution : [],
|
|
64
|
+
salt,
|
|
65
|
+
items,
|
|
66
|
+
target
|
|
67
|
+
},
|
|
68
|
+
true,
|
|
69
|
+
true,
|
|
70
|
+
false
|
|
71
|
+
),
|
|
72
|
+
captchaId
|
|
73
|
+
};
|
|
55
74
|
}
|
|
56
|
-
|
|
57
|
-
hash: computeCaptchaHash(
|
|
58
|
-
{
|
|
59
|
-
solution: solved ? item.solution : [],
|
|
60
|
-
salt,
|
|
61
|
-
items,
|
|
62
|
-
target
|
|
63
|
-
},
|
|
64
|
-
true,
|
|
65
|
-
true,
|
|
66
|
-
false
|
|
67
|
-
),
|
|
68
|
-
captchaId
|
|
69
|
-
};
|
|
70
|
-
});
|
|
75
|
+
);
|
|
71
76
|
}
|
|
72
77
|
function compareCaptchaSolutions(received, stored) {
|
|
73
78
|
if (received.length && stored.length && received.length === stored.length) {
|
|
@@ -76,19 +81,18 @@ function compareCaptchaSolutions(received, stored) {
|
|
|
76
81
|
}
|
|
77
82
|
return false;
|
|
78
83
|
}
|
|
79
|
-
function computeCaptchaHash(captcha, includeSolution
|
|
84
|
+
function computeCaptchaHash(captcha, includeSolution, includeSalt, sortItemHashes) {
|
|
80
85
|
try {
|
|
81
86
|
const itemHashes = captcha.items.map((item, index) => {
|
|
82
87
|
if (item.hash) {
|
|
83
88
|
return item.hash;
|
|
84
|
-
} else {
|
|
85
|
-
throw new common.ProsopoDatasetError("CAPTCHA.MISSING_ITEM_HASH", {
|
|
86
|
-
context: {
|
|
87
|
-
computeCaptchaHashName: computeCaptchaHash.name,
|
|
88
|
-
index
|
|
89
|
-
}
|
|
90
|
-
});
|
|
91
89
|
}
|
|
90
|
+
throw new common.ProsopoDatasetError("CAPTCHA.MISSING_ITEM_HASH", {
|
|
91
|
+
context: {
|
|
92
|
+
computeCaptchaHashName: computeCaptchaHash.name,
|
|
93
|
+
index
|
|
94
|
+
}
|
|
95
|
+
});
|
|
92
96
|
});
|
|
93
97
|
return common.hexHashArray([
|
|
94
98
|
captcha.target,
|
|
@@ -99,7 +103,9 @@ function computeCaptchaHash(captcha, includeSolution = false, includeSalt = fals
|
|
|
99
103
|
sortItemHashes ? itemHashes.sort() : itemHashes
|
|
100
104
|
]);
|
|
101
105
|
} catch (err) {
|
|
102
|
-
throw new common.ProsopoDatasetError("DATASET.HASH_ERROR", {
|
|
106
|
+
throw new common.ProsopoDatasetError("DATASET.HASH_ERROR", {
|
|
107
|
+
context: { error: err }
|
|
108
|
+
});
|
|
103
109
|
}
|
|
104
110
|
}
|
|
105
111
|
function getSolutionValueToHash(solution) {
|
|
@@ -108,11 +114,11 @@ function getSolutionValueToHash(solution) {
|
|
|
108
114
|
async function computeItemHash(item) {
|
|
109
115
|
if (item.type === "text") {
|
|
110
116
|
return { ...item, hash: common.hexHash(item.data) };
|
|
111
|
-
}
|
|
117
|
+
}
|
|
118
|
+
if (item.type === "image") {
|
|
112
119
|
return { ...item, hash: common.hexHash(await util$1.downloadImage(item.data)) };
|
|
113
|
-
} else {
|
|
114
|
-
throw new common.ProsopoDatasetError("CAPTCHA.INVALID_ITEM_FORMAT");
|
|
115
120
|
}
|
|
121
|
+
throw new common.ProsopoDatasetError("CAPTCHA.INVALID_ITEM_FORMAT");
|
|
116
122
|
}
|
|
117
123
|
function matchItemsToSolutions(solutions, items) {
|
|
118
124
|
if (!items) {
|
|
@@ -124,22 +130,30 @@ function matchItemsToSolutions(solutions, items) {
|
|
|
124
130
|
throw new common.ProsopoDatasetError("CAPTCHA.INVALID_ITEM_HASH");
|
|
125
131
|
}
|
|
126
132
|
return solution;
|
|
127
|
-
}
|
|
133
|
+
}
|
|
134
|
+
if (typeof solution === "number") {
|
|
128
135
|
const item = util.at(items, solution);
|
|
129
136
|
return item.hash;
|
|
130
|
-
} else {
|
|
131
|
-
throw new common.ProsopoDatasetError("CAPTCHA.INVALID_SOLUTION_TYPE");
|
|
132
137
|
}
|
|
138
|
+
throw new common.ProsopoDatasetError("CAPTCHA.INVALID_SOLUTION_TYPE");
|
|
133
139
|
});
|
|
134
140
|
}
|
|
135
141
|
function computeCaptchaSolutionHash(captcha) {
|
|
136
|
-
return common.hexHashArray([
|
|
142
|
+
return common.hexHashArray([
|
|
143
|
+
captcha.captchaId,
|
|
144
|
+
captcha.captchaContentId,
|
|
145
|
+
[...captcha.solution].sort(),
|
|
146
|
+
captcha.salt
|
|
147
|
+
]);
|
|
137
148
|
}
|
|
138
149
|
function computePendingRequestHash(captchaIds, userAccount, salt) {
|
|
139
150
|
return common.hexHashArray([...captchaIds.sort(), userAccount, salt]);
|
|
140
151
|
}
|
|
141
152
|
function parseCaptchaAssets(item, assetsResolver) {
|
|
142
|
-
return {
|
|
153
|
+
return {
|
|
154
|
+
...item,
|
|
155
|
+
data: assetsResolver?.resolveAsset(item.data).getURL() || item.data
|
|
156
|
+
};
|
|
143
157
|
}
|
|
144
158
|
exports.NO_SOLUTION_VALUE = NO_SOLUTION_VALUE;
|
|
145
159
|
exports.captchaSort = captchaSort;
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const merkle = require("./merkle.cjs");
|
|
4
3
|
const common = require("@prosopo/common");
|
|
5
4
|
const util = require("@prosopo/util");
|
|
6
5
|
const captcha = require("./captcha.cjs");
|
|
7
|
-
const
|
|
6
|
+
const merkle = require("./merkle.cjs");
|
|
7
|
+
const logger = common.getLogger("Info", "dataset.ts");
|
|
8
8
|
async function hashDatasetItems(datasetRaw) {
|
|
9
9
|
return datasetRaw.captchas.map(async (captcha$1) => {
|
|
10
|
-
const items = await Promise.all(
|
|
10
|
+
const items = await Promise.all(
|
|
11
|
+
captcha$1.items.map(async (item) => captcha.computeItemHash(item))
|
|
12
|
+
);
|
|
11
13
|
return {
|
|
12
14
|
...captcha$1,
|
|
13
15
|
items
|
|
@@ -26,17 +28,18 @@ async function validateDatasetContent(datasetOriginal) {
|
|
|
26
28
|
(captchaRaw2) => "captchaId" in captchaRaw2 ? captchaRaw2.captchaId === captcha2.captchaId : false
|
|
27
29
|
);
|
|
28
30
|
if (captchaRaw) {
|
|
29
|
-
return captcha2.items.every(
|
|
30
|
-
|
|
31
|
-
|
|
31
|
+
return captcha2.items.every(
|
|
32
|
+
(item, index) => item.hash === util.at(captchaRaw.items, index).hash
|
|
33
|
+
);
|
|
32
34
|
}
|
|
35
|
+
return false;
|
|
33
36
|
});
|
|
34
37
|
return hashes.every((hash) => hash);
|
|
35
38
|
}
|
|
36
39
|
async function buildDataset(datasetRaw) {
|
|
37
|
-
logger.debug(
|
|
40
|
+
logger.debug("Adding solution hashes to dataset");
|
|
38
41
|
const dataset = await addSolutionHashesToDataset(datasetRaw);
|
|
39
|
-
logger.debug(
|
|
42
|
+
logger.debug("Building dataset merkle trees");
|
|
40
43
|
const contentTree = await buildCaptchaTree(dataset, false, false, true);
|
|
41
44
|
const solutionTree = await buildCaptchaTree(dataset, true, true, false);
|
|
42
45
|
dataset.captchas = dataset.captchas.map(
|
|
@@ -73,7 +76,9 @@ function addSolutionHashesToDataset(datasetRaw) {
|
|
|
73
76
|
...captcha$1,
|
|
74
77
|
items: captcha$1.items,
|
|
75
78
|
// some captcha challenges will not have a solution
|
|
76
|
-
...captcha$1.solution !== void 0 && {
|
|
79
|
+
...captcha$1.solution !== void 0 && {
|
|
80
|
+
solution: captcha.matchItemsToSolutions(captcha$1.solution, captcha$1.items)
|
|
81
|
+
}
|
|
77
82
|
};
|
|
78
83
|
});
|
|
79
84
|
return {
|
|
@@ -13,6 +13,17 @@ class CaptchaMerkleTree {
|
|
|
13
13
|
this.leaves = [];
|
|
14
14
|
this.layers = [];
|
|
15
15
|
}
|
|
16
|
+
getRoot() {
|
|
17
|
+
if (this.root === void 0) {
|
|
18
|
+
throw new common.ProsopoError("DATASET.MERKLE_ERROR", {
|
|
19
|
+
context: {
|
|
20
|
+
error: "root undefined",
|
|
21
|
+
failedFuncName: this.getRoot.name
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
return this.root;
|
|
26
|
+
}
|
|
16
27
|
build(leaves) {
|
|
17
28
|
if (this.layers.length) {
|
|
18
29
|
this.layers = [];
|
|
@@ -37,7 +48,9 @@ class CaptchaMerkleTree {
|
|
|
37
48
|
while (leafIndex < numLeaves) {
|
|
38
49
|
const leftChild = leaves[leafIndex];
|
|
39
50
|
if (leftChild === void 0) {
|
|
40
|
-
throw new common.ProsopoError("DEVELOPER.GENERAL", {
|
|
51
|
+
throw new common.ProsopoError("DEVELOPER.GENERAL", {
|
|
52
|
+
context: { error: "leftChild undefined" }
|
|
53
|
+
});
|
|
41
54
|
}
|
|
42
55
|
const rightChild = leafIndex + 1 < numLeaves ? util.at(leaves, leafIndex + 1) : leftChild;
|
|
43
56
|
const parentNode = this.createParent(leftChild, rightChild);
|
|
@@ -49,7 +62,9 @@ class CaptchaMerkleTree {
|
|
|
49
62
|
return this.buildMerkleTree(parents);
|
|
50
63
|
}
|
|
51
64
|
createParent(leftChild, rightChild) {
|
|
52
|
-
const parent = new MerkleNode(
|
|
65
|
+
const parent = new MerkleNode(
|
|
66
|
+
common.hexHashArray([leftChild.hash, rightChild.hash])
|
|
67
|
+
);
|
|
53
68
|
leftChild.parent = parent.hash;
|
|
54
69
|
rightChild.parent = parent.hash;
|
|
55
70
|
return parent;
|
|
@@ -61,7 +76,11 @@ class CaptchaMerkleTree {
|
|
|
61
76
|
const layer = this.layers[layerNum];
|
|
62
77
|
if (layer === void 0) {
|
|
63
78
|
throw new common.ProsopoError("DATASET.MERKLE_ERROR", {
|
|
64
|
-
context: {
|
|
79
|
+
context: {
|
|
80
|
+
error: "layer undefined",
|
|
81
|
+
failedFuncName: this.proof.name,
|
|
82
|
+
layerNum
|
|
83
|
+
}
|
|
65
84
|
});
|
|
66
85
|
}
|
|
67
86
|
const leafIndex = layer.indexOf(leafHash);
|
|
@@ -6,13 +6,18 @@ async function downloadImage(url) {
|
|
|
6
6
|
const response = await fetch(url);
|
|
7
7
|
if (!response.ok) {
|
|
8
8
|
throw new common.ProsopoDatasetError("API.BAD_REQUEST", {
|
|
9
|
-
context: {
|
|
9
|
+
context: {
|
|
10
|
+
error: `Network response was not ok, status: ${response.status}`,
|
|
11
|
+
url
|
|
12
|
+
}
|
|
10
13
|
});
|
|
11
14
|
}
|
|
12
15
|
const buffer = await response.arrayBuffer();
|
|
13
16
|
return new Uint8Array(buffer);
|
|
14
17
|
} catch (err) {
|
|
15
|
-
throw new common.ProsopoEnvError("DATABASE.IMAGE_GET_FAILED", {
|
|
18
|
+
throw new common.ProsopoEnvError("DATABASE.IMAGE_GET_FAILED", {
|
|
19
|
+
context: { error: err }
|
|
20
|
+
});
|
|
16
21
|
}
|
|
17
22
|
}
|
|
18
23
|
exports.downloadImage = downloadImage;
|
|
@@ -670,7 +670,9 @@ const datasetWithSolutionHashes = {
|
|
|
670
670
|
}
|
|
671
671
|
],
|
|
672
672
|
target: "bird",
|
|
673
|
-
solution: [
|
|
673
|
+
solution: [
|
|
674
|
+
"0x15671b7ab4c6d575d51bb0c6c2a5dd05427a2938e9cbcaca1de07c23eaced17f"
|
|
675
|
+
]
|
|
674
676
|
},
|
|
675
677
|
{
|
|
676
678
|
captchaId: "0xc9d80c281e124d55441b394bec7d6a64e35c4409d57e37bcb9b9748066b095d6",
|
|
@@ -1033,7 +1035,9 @@ const datasetWithIndexSolutions = {
|
|
|
1033
1035
|
captchas: datasetWithSolutionHashes.captchas.map((captcha, index) => ({
|
|
1034
1036
|
...captcha,
|
|
1035
1037
|
//for solution in captcha.solution, find the index of captcha.item with item.hash == solution
|
|
1036
|
-
solution: captcha.solution?.map(
|
|
1038
|
+
solution: captcha.solution?.map(
|
|
1039
|
+
(solution) => captcha.items.findIndex((item) => item.hash === solution)
|
|
1040
|
+
)
|
|
1037
1041
|
}))
|
|
1038
1042
|
};
|
|
1039
1043
|
exports.datasetWithIndexSolutions = datasetWithIndexSolutions;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export * from
|
|
2
|
-
export { datasetWithSolutionHashes, datasetWithIndexSolutions } from
|
|
1
|
+
export * from "./captcha/index.js";
|
|
2
|
+
export { datasetWithSolutionHashes, datasetWithIndexSolutions, } from "./tests/mocks/data/captchas.js";
|
|
3
3
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAaA,cAAc,oBAAoB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAaA,cAAc,oBAAoB,CAAC;AACnC,OAAO,EACN,yBAAyB,EACzB,yBAAyB,GACzB,MAAM,gCAAgC,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export * from
|
|
2
|
-
export { datasetWithSolutionHashes, datasetWithIndexSolutions } from
|
|
1
|
+
export * from "./captcha/index.js";
|
|
2
|
+
export { datasetWithSolutionHashes, datasetWithIndexSolutions, } from "./tests/mocks/data/captchas.js";
|
|
3
3
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAaA,cAAc,oBAAoB,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAaA,cAAc,oBAAoB,CAAC;AACnC,OAAO,EACN,yBAAyB,EACzB,yBAAyB,GACzB,MAAM,gCAAgC,CAAC"}
|