@prosopo/datasets 3.1.54 → 3.1.56

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.
@@ -1,94 +1,76 @@
1
+ import { computeCaptchaHash, computeItemHash, matchItemsToSolutions } from "./captcha.js";
2
+ import { CaptchaMerkleTree } from "./merkle.js";
1
3
  import { ProsopoEnvError } from "@prosopo/common";
2
- import { getLogger } from "@prosopo/logger";
3
4
  import { at } from "@prosopo/util";
4
- import { computeItemHash, computeCaptchaHash, matchItemsToSolutions } from "./captcha.js";
5
- import { CaptchaMerkleTree } from "./merkle.js";
6
- const logger = getLogger("info", "datasets:captcha");
5
+ import { getLogger } from "@prosopo/logger";
6
+ //#region src/captcha/dataset.ts
7
+ var logger = getLogger("info", "datasets:captcha");
7
8
  async function hashDatasetItems(datasetRaw) {
8
- return datasetRaw.captchas.map(async (captcha) => {
9
- const items = await Promise.all(
10
- captcha.items.map(async (item) => computeItemHash(item))
11
- );
12
- return {
13
- ...captcha,
14
- items
15
- };
16
- });
9
+ return datasetRaw.captchas.map(async (captcha) => {
10
+ const items = await Promise.all(captcha.items.map(async (item) => computeItemHash(item)));
11
+ return {
12
+ ...captcha,
13
+ items
14
+ };
15
+ });
17
16
  }
17
+ /**
18
+ * Take a dataset and hash all the items, making sure that the existing captchaIds and item hashes are correct
19
+ * @param datasetOriginal
20
+ */
18
21
  async function validateDatasetContent(datasetOriginal) {
19
- const captchaPromises = await hashDatasetItems(datasetOriginal);
20
- const captchas = await Promise.all(captchaPromises);
21
- const dataset = {
22
- ...datasetOriginal,
23
- captchas
24
- };
25
- const hashes = dataset.captchas.map((captcha) => {
26
- const captchaRaw = datasetOriginal.captchas.find(
27
- (captchaRaw2) => "captchaId" in captchaRaw2 ? captchaRaw2.captchaId === captcha.captchaId : false
28
- );
29
- if (captchaRaw) {
30
- return captcha.items.every(
31
- (item, index) => item.hash === at(captchaRaw.items, index).hash
32
- );
33
- }
34
- return false;
35
- });
36
- return hashes.every((hash) => hash);
22
+ const captchaPromises = await hashDatasetItems(datasetOriginal);
23
+ const captchas = await Promise.all(captchaPromises);
24
+ return {
25
+ ...datasetOriginal,
26
+ captchas
27
+ }.captchas.map((captcha) => {
28
+ const captchaRaw = datasetOriginal.captchas.find((captchaRaw) => "captchaId" in captchaRaw ? captchaRaw.captchaId === captcha.captchaId : false);
29
+ if (captchaRaw) return captcha.items.every((item, index) => item.hash === at(captchaRaw.items, index).hash);
30
+ return false;
31
+ }).every((hash) => hash);
37
32
  }
38
33
  async function buildDataset(datasetRaw) {
39
- logger.debug(() => ({ msg: "Adding solution hashes to dataset" }));
40
- const dataset = await addSolutionHashesToDataset(datasetRaw);
41
- logger.debug(() => ({ msg: "Building dataset merkle trees" }));
42
- const contentTree = await buildCaptchaTree(dataset, false, false, true);
43
- const solutionTree = await buildCaptchaTree(dataset, true, true, false);
44
- dataset.captchas = dataset.captchas.map(
45
- (captcha, index) => ({
46
- ...captcha,
47
- captchaId: at(solutionTree.leaves, index).hash,
48
- captchaContentId: at(contentTree.leaves, index).hash,
49
- datasetId: solutionTree.root?.hash,
50
- datasetContentId: contentTree.root?.hash
51
- })
52
- );
53
- dataset.solutionTree = solutionTree.layers;
54
- dataset.contentTree = contentTree.layers;
55
- dataset.datasetId = solutionTree.root?.hash;
56
- dataset.datasetContentId = contentTree.root?.hash;
57
- return dataset;
34
+ logger.debug(() => ({ msg: "Adding solution hashes to dataset" }));
35
+ const dataset = await addSolutionHashesToDataset(datasetRaw);
36
+ logger.debug(() => ({ msg: "Building dataset merkle trees" }));
37
+ const contentTree = await buildCaptchaTree(dataset, false, false, true);
38
+ const solutionTree = await buildCaptchaTree(dataset, true, true, false);
39
+ dataset.captchas = dataset.captchas.map((captcha, index) => ({
40
+ ...captcha,
41
+ captchaId: at(solutionTree.leaves, index).hash,
42
+ captchaContentId: at(contentTree.leaves, index).hash,
43
+ datasetId: solutionTree.root?.hash,
44
+ datasetContentId: contentTree.root?.hash
45
+ }));
46
+ dataset.solutionTree = solutionTree.layers;
47
+ dataset.contentTree = contentTree.layers;
48
+ dataset.datasetId = solutionTree.root?.hash;
49
+ dataset.datasetContentId = contentTree.root?.hash;
50
+ return dataset;
58
51
  }
59
52
  async function buildCaptchaTree(dataset, includeSolution, includeSalt, sortItemHashes) {
60
- try {
61
- const tree = new CaptchaMerkleTree();
62
- const datasetWithItemHashes = { ...dataset };
63
- const captchaHashes = datasetWithItemHashes.captchas.map(
64
- (captcha) => computeCaptchaHash(captcha, includeSolution, includeSalt, sortItemHashes)
65
- );
66
- tree.build(captchaHashes);
67
- return tree;
68
- } catch (err) {
69
- throw new ProsopoEnvError("DATASET.HASH_ERROR");
70
- }
53
+ try {
54
+ const tree = new CaptchaMerkleTree();
55
+ const captchaHashes = { ...dataset }.captchas.map((captcha) => computeCaptchaHash(captcha, includeSolution, includeSalt, sortItemHashes));
56
+ tree.build(captchaHashes);
57
+ return tree;
58
+ } catch (err) {
59
+ throw new ProsopoEnvError("DATASET.HASH_ERROR");
60
+ }
71
61
  }
72
62
  function addSolutionHashesToDataset(datasetRaw) {
73
- const captchas = datasetRaw.captchas.map((captcha) => {
74
- return {
75
- ...captcha,
76
- items: captcha.items,
77
- // some captcha challenges will not have a solution
78
- ...captcha.solution !== void 0 && {
79
- solution: matchItemsToSolutions(captcha.solution, captcha.items)
80
- }
81
- };
82
- });
83
- return {
84
- ...datasetRaw,
85
- captchas
86
- };
63
+ const captchas = datasetRaw.captchas.map((captcha) => {
64
+ return {
65
+ ...captcha,
66
+ items: captcha.items,
67
+ ...captcha.solution !== void 0 && { solution: matchItemsToSolutions(captcha.solution, captcha.items) }
68
+ };
69
+ });
70
+ return {
71
+ ...datasetRaw,
72
+ captchas
73
+ };
87
74
  }
88
- export {
89
- addSolutionHashesToDataset,
90
- buildCaptchaTree,
91
- buildDataset,
92
- hashDatasetItems,
93
- validateDatasetContent
94
- };
75
+ //#endregion
76
+ export { addSolutionHashesToDataset, buildCaptchaTree, buildDataset, hashDatasetItems, validateDatasetContent };
@@ -1,27 +1,5 @@
1
+ import { downloadImage } from "./util.js";
1
2
  import { NO_SOLUTION_VALUE, captchaSort, compareCaptchaSolutions, computeCaptchaHash, computeCaptchaSolutionHash, computeItemHash, computePendingRequestHash, getSolutionValueToHash, matchItemsToSolutions, parseAndSortCaptchaSolutions, parseCaptchaAssets, parseCaptchaDataset, sortAndComputeHashes } from "./captcha.js";
2
3
  import { CaptchaMerkleTree, verifyProof } from "./merkle.js";
3
- import { downloadImage } from "./util.js";
4
4
  import { addSolutionHashesToDataset, buildCaptchaTree, buildDataset, hashDatasetItems, validateDatasetContent } from "./dataset.js";
5
- export {
6
- CaptchaMerkleTree,
7
- NO_SOLUTION_VALUE,
8
- addSolutionHashesToDataset,
9
- buildCaptchaTree,
10
- buildDataset,
11
- captchaSort,
12
- compareCaptchaSolutions,
13
- computeCaptchaHash,
14
- computeCaptchaSolutionHash,
15
- computeItemHash,
16
- computePendingRequestHash,
17
- downloadImage,
18
- getSolutionValueToHash,
19
- hashDatasetItems,
20
- matchItemsToSolutions,
21
- parseAndSortCaptchaSolutions,
22
- parseCaptchaAssets,
23
- parseCaptchaDataset,
24
- sortAndComputeHashes,
25
- validateDatasetContent,
26
- verifyProof
27
- };
5
+ export { CaptchaMerkleTree, NO_SOLUTION_VALUE, addSolutionHashesToDataset, buildCaptchaTree, buildDataset, captchaSort, compareCaptchaSolutions, computeCaptchaHash, computeCaptchaSolutionHash, computeItemHash, computePendingRequestHash, downloadImage, getSolutionValueToHash, hashDatasetItems, matchItemsToSolutions, parseAndSortCaptchaSolutions, parseCaptchaAssets, parseCaptchaDataset, sortAndComputeHashes, validateDatasetContent, verifyProof };
@@ -1,128 +1,98 @@
1
1
  import { ProsopoError } from "@prosopo/common";
2
2
  import { at } from "@prosopo/util";
3
3
  import { hexHashArray } from "@prosopo/util-crypto";
4
- class MerkleNode {
5
- constructor(hash) {
6
- this.hash = hash;
7
- this.parent = null;
8
- }
9
- }
10
- class CaptchaMerkleTree {
11
- constructor() {
12
- this.leaves = [];
13
- this.layers = [];
14
- }
15
- getRoot() {
16
- if (this.root === void 0) {
17
- throw new ProsopoError("DATASET.MERKLE_ERROR", {
18
- context: {
19
- error: "root undefined",
20
- failedFuncName: this.getRoot.name
21
- }
22
- });
23
- }
24
- return this.root;
25
- }
26
- build(leaves) {
27
- if (this.layers.length) {
28
- this.layers = [];
29
- }
30
- const layerZero = [];
31
- for (const leaf of leaves) {
32
- const node = new MerkleNode(leaf);
33
- this.leaves.push(node);
34
- layerZero.push(node.hash);
35
- }
36
- this.layers.push(layerZero);
37
- this.root = this.buildMerkleTree(this.leaves)[0];
38
- }
39
- buildMerkleTree(leaves) {
40
- const numLeaves = leaves.length;
41
- if (numLeaves === 1) {
42
- return leaves;
43
- }
44
- const parents = [];
45
- let leafIndex = 0;
46
- const newLayer = [];
47
- while (leafIndex < numLeaves) {
48
- const leftChild = leaves[leafIndex];
49
- if (leftChild === void 0) {
50
- throw new ProsopoError("DEVELOPER.GENERAL", {
51
- context: { error: "leftChild undefined" }
52
- });
53
- }
54
- const rightChild = leafIndex + 1 < numLeaves ? at(leaves, leafIndex + 1) : leftChild;
55
- const parentNode = this.createParent(leftChild, rightChild);
56
- newLayer.push(parentNode.hash);
57
- parents.push(parentNode);
58
- leafIndex += 2;
59
- }
60
- this.layers.push(newLayer);
61
- return this.buildMerkleTree(parents);
62
- }
63
- createParent(leftChild, rightChild) {
64
- const parent = new MerkleNode(
65
- hexHashArray([leftChild.hash, rightChild.hash])
66
- );
67
- leftChild.parent = parent.hash;
68
- rightChild.parent = parent.hash;
69
- return parent;
70
- }
71
- proof(leafHash) {
72
- const proofTree = [];
73
- let layerNum = 0;
74
- while (layerNum < this.layers.length - 1) {
75
- const layer = this.layers[layerNum];
76
- if (layer === void 0) {
77
- throw new ProsopoError("DATASET.MERKLE_ERROR", {
78
- context: {
79
- error: "layer undefined",
80
- failedFuncName: this.proof.name,
81
- layerNum
82
- }
83
- });
84
- }
85
- const leafIndex = layer.indexOf(leafHash);
86
- let partnerIndex = leafIndex % 2 && leafIndex > 0 ? leafIndex - 1 : leafIndex + 1;
87
- if (partnerIndex > layer.length - 1) {
88
- partnerIndex = leafIndex;
89
- }
90
- const pair = [leafHash];
91
- const partner = at(layer, partnerIndex);
92
- if (partnerIndex > leafIndex) {
93
- pair.push(partner);
94
- } else {
95
- pair.unshift(partner);
96
- }
97
- proofTree.push([at(pair, 0), at(pair, 1)]);
98
- layerNum += 1;
99
- leafHash = hexHashArray(pair);
100
- }
101
- const last = at(this.layers, this.layers.length - 1);
102
- return [...proofTree, [at(last, 0)]];
103
- }
104
- }
4
+ //#region src/captcha/merkle.ts
5
+ var MerkleNode = class {
6
+ constructor(hash) {
7
+ this.hash = hash;
8
+ this.parent = null;
9
+ }
10
+ };
11
+ var CaptchaMerkleTree = class {
12
+ constructor() {
13
+ this.leaves = [];
14
+ this.layers = [];
15
+ }
16
+ getRoot() {
17
+ if (this.root === void 0) throw new ProsopoError("DATASET.MERKLE_ERROR", { context: {
18
+ error: "root undefined",
19
+ failedFuncName: this.getRoot.name
20
+ } });
21
+ return this.root;
22
+ }
23
+ build(leaves) {
24
+ if (this.layers.length) this.layers = [];
25
+ const layerZero = [];
26
+ for (const leaf of leaves) {
27
+ const node = new MerkleNode(leaf);
28
+ this.leaves.push(node);
29
+ layerZero.push(node.hash);
30
+ }
31
+ this.layers.push(layerZero);
32
+ this.root = this.buildMerkleTree(this.leaves)[0];
33
+ }
34
+ buildMerkleTree(leaves) {
35
+ const numLeaves = leaves.length;
36
+ if (numLeaves === 1) return leaves;
37
+ const parents = [];
38
+ let leafIndex = 0;
39
+ const newLayer = [];
40
+ while (leafIndex < numLeaves) {
41
+ const leftChild = leaves[leafIndex];
42
+ if (leftChild === void 0) throw new ProsopoError("DEVELOPER.GENERAL", { context: { error: "leftChild undefined" } });
43
+ const rightChild = leafIndex + 1 < numLeaves ? at(leaves, leafIndex + 1) : leftChild;
44
+ const parentNode = this.createParent(leftChild, rightChild);
45
+ newLayer.push(parentNode.hash);
46
+ parents.push(parentNode);
47
+ leafIndex += 2;
48
+ }
49
+ this.layers.push(newLayer);
50
+ return this.buildMerkleTree(parents);
51
+ }
52
+ createParent(leftChild, rightChild) {
53
+ const parent = new MerkleNode(hexHashArray([leftChild.hash, rightChild.hash]));
54
+ leftChild.parent = parent.hash;
55
+ rightChild.parent = parent.hash;
56
+ return parent;
57
+ }
58
+ proof(leafHash) {
59
+ const proofTree = [];
60
+ let layerNum = 0;
61
+ while (layerNum < this.layers.length - 1) {
62
+ const layer = this.layers[layerNum];
63
+ if (layer === void 0) throw new ProsopoError("DATASET.MERKLE_ERROR", { context: {
64
+ error: "layer undefined",
65
+ failedFuncName: this.proof.name,
66
+ layerNum
67
+ } });
68
+ const leafIndex = layer.indexOf(leafHash);
69
+ let partnerIndex = leafIndex % 2 && leafIndex > 0 ? leafIndex - 1 : leafIndex + 1;
70
+ if (partnerIndex > layer.length - 1) partnerIndex = leafIndex;
71
+ const pair = [leafHash];
72
+ const partner = at(layer, partnerIndex);
73
+ if (partnerIndex > leafIndex) pair.push(partner);
74
+ else pair.unshift(partner);
75
+ proofTree.push([at(pair, 0), at(pair, 1)]);
76
+ layerNum += 1;
77
+ leafHash = hexHashArray(pair);
78
+ }
79
+ const last = at(this.layers, this.layers.length - 1);
80
+ return [...proofTree, [at(last, 0)]];
81
+ }
82
+ };
105
83
  function verifyProof(leaf, proof) {
106
- try {
107
- if (at(proof, 0).indexOf(leaf) === -1) {
108
- return false;
109
- }
110
- for (const [layerIndex, layer] of proof.entries()) {
111
- leaf = hexHashArray(layer);
112
- if (at(proof, layerIndex + 1).indexOf(leaf) === -1) {
113
- return false;
114
- }
115
- const last = at(proof, proof.length - 1);
116
- if (leaf === at(last, 0)) {
117
- return true;
118
- }
119
- }
120
- return false;
121
- } catch (err) {
122
- return false;
123
- }
84
+ try {
85
+ if (at(proof, 0).indexOf(leaf) === -1) return false;
86
+ for (const [layerIndex, layer] of proof.entries()) {
87
+ leaf = hexHashArray(layer);
88
+ if (at(proof, layerIndex + 1).indexOf(leaf) === -1) return false;
89
+ const last = at(proof, proof.length - 1);
90
+ if (leaf === at(last, 0)) return true;
91
+ }
92
+ return false;
93
+ } catch (err) {
94
+ return false;
95
+ }
124
96
  }
125
- export {
126
- CaptchaMerkleTree,
127
- verifyProof
128
- };
97
+ //#endregion
98
+ export { CaptchaMerkleTree, verifyProof };
@@ -1,23 +1,17 @@
1
1
  import { ProsopoDatasetError, ProsopoEnvError } from "@prosopo/common";
2
+ //#region src/captcha/util.ts
2
3
  async function downloadImage(url) {
3
- try {
4
- const response = await fetch(url);
5
- if (!response.ok) {
6
- throw new ProsopoDatasetError("API.BAD_REQUEST", {
7
- context: {
8
- error: `Network response was not ok, status: ${response.status}`,
9
- url
10
- }
11
- });
12
- }
13
- const buffer = await response.arrayBuffer();
14
- return new Uint8Array(buffer);
15
- } catch (err) {
16
- throw new ProsopoEnvError("DATABASE.IMAGE_GET_FAILED", {
17
- context: { error: err }
18
- });
19
- }
4
+ try {
5
+ const response = await fetch(url);
6
+ if (!response.ok) throw new ProsopoDatasetError("API.BAD_REQUEST", { context: {
7
+ error: `Network response was not ok, status: ${response.status}`,
8
+ url
9
+ } });
10
+ const buffer = await response.arrayBuffer();
11
+ return new Uint8Array(buffer);
12
+ } catch (err) {
13
+ throw new ProsopoEnvError("DATABASE.IMAGE_GET_FAILED", { context: { error: err } });
14
+ }
20
15
  }
21
- export {
22
- downloadImage
23
- };
16
+ //#endregion
17
+ export { downloadImage };