@prosopo/provider 0.1.17 → 0.1.18

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.
Files changed (42) hide show
  1. package/package.json +11 -11
  2. package/coverage/tmp/coverage-14066-1690288461446-0.json +0 -1
  3. package/dist/api/admin.d.ts +0 -2
  4. package/dist/api/admin.d.ts.map +0 -1
  5. package/dist/api/admin.js +0 -58
  6. package/dist/api/admin.js.map +0 -1
  7. package/dist/api/captcha.d.ts +0 -10
  8. package/dist/api/captcha.d.ts.map +0 -1
  9. package/dist/api/captcha.js +0 -155
  10. package/dist/api/captcha.js.map +0 -1
  11. package/dist/batch/commitments.d.ts +0 -23
  12. package/dist/batch/commitments.d.ts.map +0 -1
  13. package/dist/batch/commitments.js +0 -149
  14. package/dist/batch/commitments.js.map +0 -1
  15. package/dist/batch/index.d.ts +0 -2
  16. package/dist/batch/index.d.ts.map +0 -1
  17. package/dist/batch/index.js +0 -15
  18. package/dist/batch/index.js.map +0 -1
  19. package/dist/index.d.ts +0 -5
  20. package/dist/index.d.ts.map +0 -1
  21. package/dist/index.js +0 -18
  22. package/dist/index.js.map +0 -1
  23. package/dist/scheduler.d.ts +0 -5
  24. package/dist/scheduler.d.ts.map +0 -1
  25. package/dist/scheduler.js +0 -48
  26. package/dist/scheduler.js.map +0 -1
  27. package/dist/tasks/calculateSolutions.d.ts +0 -10
  28. package/dist/tasks/calculateSolutions.d.ts.map +0 -1
  29. package/dist/tasks/calculateSolutions.js +0 -90
  30. package/dist/tasks/calculateSolutions.js.map +0 -1
  31. package/dist/tasks/index.d.ts +0 -3
  32. package/dist/tasks/index.d.ts.map +0 -1
  33. package/dist/tasks/index.js +0 -16
  34. package/dist/tasks/index.js.map +0 -1
  35. package/dist/tasks/tasks.d.ts +0 -108
  36. package/dist/tasks/tasks.d.ts.map +0 -1
  37. package/dist/tasks/tasks.js +0 -370
  38. package/dist/tasks/tasks.js.map +0 -1
  39. package/dist/util.d.ts +0 -28
  40. package/dist/util.d.ts.map +0 -1
  41. package/dist/util.js +0 -110
  42. package/dist/util.js.map +0 -1
@@ -1,90 +0,0 @@
1
- // Copyright 2021-2023 Prosopo (UK) Ltd.
2
- //
3
- // Licensed under the Apache License, Version 2.0 (the "License");
4
- // you may not use this file except in compliance with the License.
5
- // You may obtain a copy of the License at
6
- //
7
- // http://www.apache.org/licenses/LICENSE-2.0
8
- //
9
- // Unless required by applicable law or agreed to in writing, software
10
- // distributed under the License is distributed on an "AS IS" BASIS,
11
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- // See the License for the specific language governing permissions and
13
- // limitations under the License.
14
- import { CaptchaStates } from '@prosopo/types';
15
- import { ProsopoEnvError, getLogger } from '@prosopo/common';
16
- import { ScheduledTaskNames } from '@prosopo/types';
17
- import { Tasks } from './tasks.js';
18
- import { calculateNewSolutions, checkIfTaskIsRunning, updateSolutions } from '../util.js';
19
- import { captchaSort } from '@prosopo/datasets';
20
- export class CalculateSolutionsTask extends Tasks {
21
- constructor(env) {
22
- super(env);
23
- this.logger = getLogger(env.config.logLevel, 'CalculateSolutionsTask');
24
- }
25
- /**
26
- * Apply new captcha solutions to captcha dataset and recalculate merkle tree
27
- */
28
- async run() {
29
- try {
30
- const taskRunning = await checkIfTaskIsRunning(ScheduledTaskNames.CalculateSolution, this.db);
31
- if (!taskRunning) {
32
- // Get the current datasetId from the contract
33
- const provider = (await this.contract.methods.getProvider(this.contract.pair.address, {})).value
34
- .unwrap()
35
- .unwrap();
36
- // Get any unsolved CAPTCHA challenges from the database for this datasetId
37
- const unsolvedCaptchas = await this.db.getAllCaptchasByDatasetId(provider.datasetId.toString(), CaptchaStates.Unsolved);
38
- // edge case when a captcha dataset contains no unsolved CAPTCHA challenges
39
- if (!unsolvedCaptchas) {
40
- return 0;
41
- }
42
- // Sort the unsolved CAPTCHA challenges by their captchaId
43
- const unsolvedSorted = unsolvedCaptchas.sort(captchaSort);
44
- this.logger.info(`There are ${unsolvedSorted.length} unsolved CAPTCHA challenges`);
45
- // Get the solution configuration from the config file
46
- const requiredNumberOfSolutions = this.captchaSolutionConfig.requiredNumberOfSolutions;
47
- const winningPercentage = this.captchaSolutionConfig.solutionWinningPercentage;
48
- const winningNumberOfSolutions = Math.round(requiredNumberOfSolutions * (winningPercentage / 100));
49
- if (unsolvedSorted && unsolvedSorted.length > 0) {
50
- const captchaIds = unsolvedSorted.map((captcha) => captcha.captchaId);
51
- const solutions = (await this.db.getAllDappUserSolutions(captchaIds)) || [];
52
- const solutionsToUpdate = calculateNewSolutions(solutions, winningNumberOfSolutions);
53
- if (solutionsToUpdate.rows().length > 0) {
54
- this.logger.info(`There are ${solutionsToUpdate.rows().length} CAPTCHA challenges to update with solutions`);
55
- try {
56
- const captchaIdsToUpdate = [...solutionsToUpdate['captchaId'].values()];
57
- const commitmentIds = solutions
58
- .filter((s) => captchaIdsToUpdate.indexOf(s.captchaId) > -1)
59
- .map((s) => s.commitmentId);
60
- const dataset = await this.db.getDataset(provider.datasetId.toString());
61
- dataset.captchas = updateSolutions(solutionsToUpdate, dataset.captchas, this.logger);
62
- // store new solutions in database
63
- await this.providerSetDataset(dataset);
64
- // mark user solutions as used to calculate new solutions
65
- await this.db.flagProcessedDappUserSolutions(captchaIdsToUpdate);
66
- // mark user commitments as used to calculate new solutions
67
- await this.db.flagProcessedDappUserCommitments(commitmentIds);
68
- // remove old captcha challenges from database
69
- await this.db.removeCaptchas(captchaIdsToUpdate);
70
- return solutionsToUpdate.rows().length;
71
- }
72
- catch (error) {
73
- this.logger.error(error);
74
- }
75
- }
76
- return 0;
77
- }
78
- else {
79
- this.logger.info(`There are no CAPTCHA challenges that require their solutions to be updated`);
80
- return 0;
81
- }
82
- }
83
- return 0;
84
- }
85
- catch (error) {
86
- throw new ProsopoEnvError(error, 'GENERAL.CALCULATE_CAPTCHA_SOLUTION');
87
- }
88
- }
89
- }
90
- //# sourceMappingURL=calculateSolutions.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"calculateSolutions.js","sourceRoot":"","sources":["../../src/tasks/calculateSolutions.ts"],"names":[],"mappings":"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"}
@@ -1,3 +0,0 @@
1
- export * from './tasks.js';
2
- export * from './calculateSolutions.js';
3
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tasks/index.ts"],"names":[],"mappings":"AAaA,cAAc,YAAY,CAAA;AAC1B,cAAc,yBAAyB,CAAA"}
@@ -1,16 +0,0 @@
1
- // Copyright 2021-2023 Prosopo (UK) Ltd.
2
- //
3
- // Licensed under the Apache License, Version 2.0 (the "License");
4
- // you may not use this file except in compliance with the License.
5
- // You may obtain a copy of the License at
6
- //
7
- // http://www.apache.org/licenses/LICENSE-2.0
8
- //
9
- // Unless required by applicable law or agreed to in writing, software
10
- // distributed under the License is distributed on an "AS IS" BASIS,
11
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- // See the License for the specific language governing permissions and
13
- // limitations under the License.
14
- export * from './tasks.js';
15
- export * from './calculateSolutions.js';
16
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tasks/index.ts"],"names":[],"mappings":"AAAA,wCAAwC;AACxC,EAAE;AACF,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,iDAAiD;AACjD,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;AACjC,cAAc,YAAY,CAAA;AAC1B,cAAc,yBAAyB,CAAA"}
@@ -1,108 +0,0 @@
1
- import { ArgumentTypes, Captcha, CaptchaConfig, CaptchaSolution, CaptchaSolutionConfig, CaptchaWithProof, DappUserSolutionResult, DatasetRaw, DatasetWithIds, Hash, PendingCaptchaRequest, ProsopoConfig, Provider, ProviderRegistered } from '@prosopo/types';
2
- import { Header } from '@polkadot/types/interfaces';
3
- import { CaptchaMerkleTree } from '@prosopo/datasets';
4
- import { Database, UserCommitmentRecord } from '@prosopo/types-database';
5
- import { Logger } from '@prosopo/common';
6
- import { ProsopoCaptchaContract } from '@prosopo/contract';
7
- import { ProviderEnvironment } from '@prosopo/types-env';
8
- import { SubmittableResult } from '@polkadot/api';
9
- /**
10
- * @description Tasks that are shared by the API and CLI
11
- */
12
- export declare class Tasks {
13
- contract: ProsopoCaptchaContract;
14
- db: Database;
15
- captchaConfig: CaptchaConfig;
16
- captchaSolutionConfig: CaptchaSolutionConfig;
17
- logger: Logger;
18
- config: ProsopoConfig;
19
- constructor(env: ProviderEnvironment);
20
- providerSetDatasetFromFile(file: JSON): Promise<SubmittableResult | undefined>;
21
- providerSetDataset(datasetRaw: DatasetRaw): Promise<SubmittableResult | undefined>;
22
- /**
23
- * @description Get random captchas that are solved or not solved, along with the merkle proof for each
24
- * @param {string} datasetId the id of the data set
25
- * @param {boolean} solved `true` when captcha is solved
26
- * @param {number} size the number of records to be returned
27
- */
28
- getCaptchaWithProof(datasetId: ArgumentTypes.Hash, solved: boolean, size: number): Promise<CaptchaWithProof[]>;
29
- /**
30
- * Validate and store the text captcha solution(s) from the Dapp User in a web2 environment
31
- * @param {string} userAccount
32
- * @param {string} dappAccount
33
- * @param {string} requestHash
34
- * @param {JSON} captchas
35
- * @param {string} signature
36
- * @return {Promise<DappUserSolutionResult>} result containing the contract event
37
- */
38
- dappUserSolution(userAccount: string, dappAccount: string, requestHash: string, captchas: CaptchaSolution[], signature: string): Promise<DappUserSolutionResult>;
39
- /**
40
- * Validate that the dapp is active in the contract
41
- */
42
- dappIsActive(dappAccount: string): Promise<boolean>;
43
- /**
44
- * Gets provider status in contract
45
- */
46
- providerStatus(): Promise<ProviderRegistered>;
47
- /**
48
- * Validate length of received captchas array matches length of captchas found in database
49
- * Validate that the datasetId is the same for all captchas and is equal to the datasetId on the stored captchas
50
- */
51
- validateReceivedCaptchasAgainstStoredCaptchas(captchas: CaptchaSolution[]): Promise<{
52
- storedCaptchas: Captcha[];
53
- receivedCaptchas: CaptchaSolution[];
54
- captchaIds: string[];
55
- }>;
56
- /**
57
- * Build merkle tree and get commitment from contract, returning the tree, commitment, and commitmentId
58
- * @param {CaptchaSolution[]} captchaSolutions
59
- * @returns {Promise<{ tree: CaptchaMerkleTree, commitment: CaptchaSolutionCommitment, commitmentId: string }>}
60
- */
61
- buildTreeAndGetCommitmentId(captchaSolutions: CaptchaSolution[]): Promise<{
62
- tree: CaptchaMerkleTree;
63
- commitmentId: string;
64
- }>;
65
- /**
66
- * Validate that a Dapp User is responding to their own pending captcha request
67
- * @param {string} requestHash
68
- * @param {PendingCaptchaRequest} pendingRecord
69
- * @param {string} userAccount
70
- * @param {string[]} captchaIds
71
- */
72
- validateDappUserSolutionRequestIsPending(requestHash: string, pendingRecord: PendingCaptchaRequest, userAccount: string, captchaIds: string[]): Promise<boolean>;
73
- /**
74
- * Get two random captchas from specified dataset, create the response and store a hash of it, marked as pending
75
- * @param {string} datasetId
76
- * @param {string} userAccount
77
- */
78
- getRandomCaptchasAndRequestHash(datasetId: string, userAccount: string): Promise<{
79
- captchas: CaptchaWithProof[];
80
- requestHash: string;
81
- }>;
82
- /**
83
- * Block by block search for blockNo
84
- */
85
- isRecentBlock(contract: any, header: Header, blockNo: number, depth?: number): any;
86
- /**
87
- * Validate that provided `datasetId` was a result of calling `get_random_provider` method
88
- * @param {string} userAccount - Same user that called `get_random_provider`
89
- * @param {string} dappContractAccount - account of dapp that is requesting captcha
90
- * @param {string} datasetId - `captcha_dataset_id` from the result of `get_random_provider`
91
- * @param {string} blockNumber - Block on which `get_random_provider` was called
92
- */
93
- validateProviderWasRandomlyChosen(userAccount: string, dappContractAccount: string, datasetId: string | Hash, blockNumber: number): Promise<void>;
94
- /**
95
- * Get payment info for a transaction
96
- * @param {string} userAccount
97
- * @param {string} blockHash
98
- * @param {string} txHash
99
- * @returns {Promise<RuntimeDispatchInfo|null>}
100
- */
101
- private getPaymentInfo;
102
- getDappUserCommitmentById(commitmentId: string): Promise<UserCommitmentRecord>;
103
- getDappUserCommitmentByAccount(userAccount: string): Promise<UserCommitmentRecord | undefined>;
104
- getProviderDetails(): Promise<Provider>;
105
- /** Get the dataset from the databse */
106
- getProviderDataset(datasetId: string): Promise<DatasetWithIds>;
107
- }
108
- //# sourceMappingURL=tasks.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"tasks.d.ts","sourceRoot":"","sources":["../../src/tasks/tasks.ts"],"names":[],"mappings":"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"}
@@ -1,370 +0,0 @@
1
- // Copyright 2021-2023 Prosopo (UK) Ltd.
2
- //
3
- // Licensed under the Apache License, Version 2.0 (the "License");
4
- // you may not use this file except in compliance with the License.
5
- // You may obtain a copy of the License at
6
- //
7
- // http://www.apache.org/licenses/LICENSE-2.0
8
- //
9
- // Unless required by applicable law or agreed to in writing, software
10
- // distributed under the License is distributed on an "AS IS" BASIS,
11
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- // See the License for the specific language governing permissions and
13
- // limitations under the License.
14
- import { ArgumentTypes, CaptchaStatus, } from '@prosopo/types';
15
- import { CaptchaMerkleTree, buildDataset, compareCaptchaSolutions, computeCaptchaSolutionHash, computePendingRequestHash, parseAndSortCaptchaSolutions, parseCaptchaDataset, } from '@prosopo/datasets';
16
- import { ProsopoEnvError, getLogger } from '@prosopo/common';
17
- import { getBlockNumber, wrapQuery } from '@prosopo/contract';
18
- import { hexToU8a, stringToHex } from '@polkadot/util';
19
- import { randomAsHex, signatureVerify } from '@polkadot/util-crypto';
20
- import { shuffleArray } from '../util.js';
21
- /**
22
- * @description Tasks that are shared by the API and CLI
23
- */
24
- export class Tasks {
25
- contract;
26
- db;
27
- captchaConfig;
28
- captchaSolutionConfig;
29
- logger;
30
- config;
31
- constructor(env) {
32
- if (!env.contractInterface) {
33
- throw new ProsopoEnvError('CONTRACT.CONTRACT_UNDEFINED', this.constructor.name, {}, { contractAddress: env.contractAddress });
34
- }
35
- this.config = env.config;
36
- this.contract = env.contractInterface;
37
- this.db = env.db;
38
- this.captchaConfig = env.config.captchas;
39
- this.captchaSolutionConfig = env.config.captchaSolutions;
40
- this.logger = getLogger(env.config.logLevel, 'Tasks');
41
- }
42
- async providerSetDatasetFromFile(file) {
43
- const datasetRaw = parseCaptchaDataset(file);
44
- this.logger.debug('Parsed raw data set');
45
- return await this.providerSetDataset(datasetRaw);
46
- }
47
- async providerSetDataset(datasetRaw) {
48
- // check that the number of captchas contained within dataset.captchas is greater than or equal to the total
49
- // number of captchas that must be served
50
- if (datasetRaw.captchas.length < this.config.captchas.solved.count + this.config.captchas.unsolved.count) {
51
- throw new ProsopoEnvError('DATASET.CAPTCHAS_COUNT_LESS_THAN_CONFIGURED', this.providerSetDataset.name);
52
- }
53
- // check that the number of solutions contained within dataset.captchas is greater than or equal to the number
54
- // of solved captchas that must be served
55
- const solutions = datasetRaw.captchas
56
- .map((captcha) => (captcha.solution ? 1 : 0))
57
- .reduce((partialSum, b) => partialSum + b, 0);
58
- if (solutions < this.config.captchas.solved.count) {
59
- throw new ProsopoEnvError('DATASET.SOLUTIONS_COUNT_LESS_THAN_CONFIGURED', this.providerSetDataset.name);
60
- }
61
- const dataset = await buildDataset(datasetRaw);
62
- if (!dataset.datasetId || !dataset.datasetContentId) {
63
- throw new ProsopoEnvError('DATASET.DATASET_ID_UNDEFINED', this.providerSetDataset.name);
64
- }
65
- await this.db?.storeDataset(dataset);
66
- // catch any errors before running the tx
67
- await wrapQuery(this.contract.query.providerSetDataset, this.contract.query)(dataset.datasetId, dataset.datasetContentId);
68
- const txResult = await this.contract.methods.providerSetDataset(dataset.datasetId, dataset.datasetContentId, {
69
- value: 0,
70
- });
71
- return txResult.result;
72
- }
73
- // Other tasks
74
- /**
75
- * @description Get random captchas that are solved or not solved, along with the merkle proof for each
76
- * @param {string} datasetId the id of the data set
77
- * @param {boolean} solved `true` when captcha is solved
78
- * @param {number} size the number of records to be returned
79
- */
80
- async getCaptchaWithProof(datasetId, solved, size) {
81
- const captchaDocs = await this.db.getRandomCaptcha(solved, datasetId, size);
82
- if (captchaDocs) {
83
- const captchas = [];
84
- for (const captcha of captchaDocs) {
85
- const datasetDetails = await this.db.getDatasetDetails(datasetId);
86
- const tree = new CaptchaMerkleTree();
87
- if (datasetDetails.contentTree) {
88
- tree.layers = datasetDetails.contentTree;
89
- const proof = tree.proof(captcha.captchaContentId);
90
- // cannot pass solution to dapp user as they are required to solve the captcha!
91
- delete captcha.solution;
92
- captcha.items = shuffleArray(captcha.items);
93
- captchas.push({ captcha, proof });
94
- }
95
- }
96
- return captchas;
97
- }
98
- throw new ProsopoEnvError('DATABASE.CAPTCHA_GET_FAILED', this.getCaptchaWithProof.name, {}, { datasetId, solved, size });
99
- }
100
- /**
101
- * Validate and store the text captcha solution(s) from the Dapp User in a web2 environment
102
- * @param {string} userAccount
103
- * @param {string} dappAccount
104
- * @param {string} requestHash
105
- * @param {JSON} captchas
106
- * @param {string} signature
107
- * @return {Promise<DappUserSolutionResult>} result containing the contract event
108
- */
109
- async dappUserSolution(userAccount, dappAccount, requestHash, captchas, signature // the signature to indicate ownership of account (web2 only)
110
- ) {
111
- if (!(await this.dappIsActive(dappAccount))) {
112
- throw new ProsopoEnvError('CONTRACT.DAPP_NOT_ACTIVE', this.getPaymentInfo.name, {}, { dappAccount });
113
- }
114
- // check that the signature is valid (i.e. the web2 user has signed the message with their private key, proving they own their account)
115
- const verification = signatureVerify(stringToHex(requestHash), signature, userAccount);
116
- if (!verification.isValid) {
117
- // the signature is not valid, so the user is not the owner of the account. May have given a false account address with good reputation in an attempt to impersonate
118
- throw new ProsopoEnvError('GENERAL.INVALID_SIGNATURE', this.dappUserSolution.name, {}, { userAccount });
119
- }
120
- let response = {
121
- captchas: [],
122
- solutionApproved: false,
123
- };
124
- const { storedCaptchas, receivedCaptchas, captchaIds } = await this.validateReceivedCaptchasAgainstStoredCaptchas(captchas);
125
- const { tree, commitmentId } = await this.buildTreeAndGetCommitmentId(receivedCaptchas);
126
- const provider = (await this.contract.methods.getProvider(this.contract.pair.address, {})).value
127
- .unwrap()
128
- .unwrap();
129
- const pendingRecord = await this.db.getDappUserPending(requestHash);
130
- const pendingRequest = await this.validateDappUserSolutionRequestIsPending(requestHash, pendingRecord, userAccount, captchaIds);
131
- // Only do stuff if the request is in the local DB
132
- const userSignature = hexToU8a(signature);
133
- const blockNumber = (await getBlockNumber(this.contract.api)).toNumber();
134
- if (pendingRequest) {
135
- const commit = {
136
- id: commitmentId,
137
- userAccount: userAccount,
138
- dappContract: dappAccount,
139
- providerAccount: this.contract.pair.address,
140
- datasetId: provider.datasetId.toString(),
141
- status: CaptchaStatus.pending,
142
- userSignature: Array.from(userSignature),
143
- requestedAt: pendingRecord.requestedAtBlock,
144
- completedAt: blockNumber,
145
- processed: false,
146
- batched: false,
147
- };
148
- await this.db.storeDappUserSolution(receivedCaptchas, commit);
149
- if (compareCaptchaSolutions(receivedCaptchas, storedCaptchas)) {
150
- response = {
151
- captchas: captchaIds.map((id) => ({
152
- captchaId: id,
153
- proof: tree.proof(id),
154
- })),
155
- solutionApproved: true,
156
- };
157
- await this.db.approveDappUserCommitment(commitmentId);
158
- }
159
- else {
160
- response = {
161
- captchas: captchaIds.map((id) => ({
162
- captchaId: id,
163
- proof: [[]],
164
- })),
165
- solutionApproved: false,
166
- };
167
- }
168
- }
169
- return response;
170
- }
171
- /**
172
- * Validate that the dapp is active in the contract
173
- */
174
- async dappIsActive(dappAccount) {
175
- const dapp = await wrapQuery(this.contract.query.getDapp, this.contract.query)(dappAccount);
176
- //dapp.status.isActive doesn't work: https://substrate.stackexchange.com/questions/6333/how-do-we-work-with-polkadot-js-enums-in-typescript
177
- return dapp.status.toString() === 'Active';
178
- }
179
- /**
180
- * Gets provider status in contract
181
- */
182
- async providerStatus() {
183
- try {
184
- const provider = await wrapQuery(this.contract.query.getProvider, this.contract.query)(this.contract.pair.address);
185
- return { status: provider.status ? 'Registered' : 'Unregistered' };
186
- }
187
- catch (e) {
188
- return { status: 'Unregistered' };
189
- }
190
- }
191
- /**
192
- * Validate length of received captchas array matches length of captchas found in database
193
- * Validate that the datasetId is the same for all captchas and is equal to the datasetId on the stored captchas
194
- */
195
- async validateReceivedCaptchasAgainstStoredCaptchas(captchas) {
196
- const receivedCaptchas = parseAndSortCaptchaSolutions(captchas);
197
- const captchaIds = receivedCaptchas.map((captcha) => captcha.captchaId);
198
- const storedCaptchas = await this.db.getCaptchaById(captchaIds);
199
- if (!storedCaptchas || receivedCaptchas.length !== storedCaptchas.length) {
200
- throw new ProsopoEnvError('CAPTCHA.INVALID_CAPTCHA_ID', this.validateReceivedCaptchasAgainstStoredCaptchas.name, {}, captchas);
201
- }
202
- if (!storedCaptchas.every((captcha) => captcha.datasetId === storedCaptchas[0].datasetId)) {
203
- throw new ProsopoEnvError('CAPTCHA.DIFFERENT_DATASET_IDS', this.validateReceivedCaptchasAgainstStoredCaptchas.name, {}, captchas);
204
- }
205
- return { storedCaptchas, receivedCaptchas, captchaIds };
206
- }
207
- /**
208
- * Build merkle tree and get commitment from contract, returning the tree, commitment, and commitmentId
209
- * @param {CaptchaSolution[]} captchaSolutions
210
- * @returns {Promise<{ tree: CaptchaMerkleTree, commitment: CaptchaSolutionCommitment, commitmentId: string }>}
211
- */
212
- async buildTreeAndGetCommitmentId(captchaSolutions) {
213
- const tree = new CaptchaMerkleTree();
214
- const solutionsHashed = captchaSolutions.map((captcha) => computeCaptchaSolutionHash(captcha));
215
- tree.build(solutionsHashed);
216
- const commitmentId = tree.root?.hash;
217
- if (!commitmentId) {
218
- throw new ProsopoEnvError('CONTRACT.CAPTCHA_SOLUTION_COMMITMENT_DOES_NOT_EXIST', this.buildTreeAndGetCommitmentId.name, {}, { commitmentId: commitmentId });
219
- }
220
- return { tree, commitmentId };
221
- }
222
- /**
223
- * Validate that a Dapp User is responding to their own pending captcha request
224
- * @param {string} requestHash
225
- * @param {PendingCaptchaRequest} pendingRecord
226
- * @param {string} userAccount
227
- * @param {string[]} captchaIds
228
- */
229
- async validateDappUserSolutionRequestIsPending(requestHash, pendingRecord, userAccount, captchaIds) {
230
- const currentTime = Date.now();
231
- if (pendingRecord.deadlineTimestamp < currentTime) {
232
- // deadline for responding to the captcha has expired
233
- this.logger.info('Deadline for responding to captcha has expired');
234
- return false;
235
- }
236
- if (pendingRecord) {
237
- const pendingHashComputed = computePendingRequestHash(captchaIds, userAccount, pendingRecord.salt);
238
- return requestHash === pendingHashComputed;
239
- }
240
- return false;
241
- }
242
- /**
243
- * Get two random captchas from specified dataset, create the response and store a hash of it, marked as pending
244
- * @param {string} datasetId
245
- * @param {string} userAccount
246
- */
247
- async getRandomCaptchasAndRequestHash(datasetId, userAccount) {
248
- const dataset = await this.db.getDatasetDetails(datasetId);
249
- if (!dataset) {
250
- throw new ProsopoEnvError('DATABASE.DATASET_GET_FAILED');
251
- }
252
- const unsolvedCount = Math.abs(Math.trunc(this.captchaConfig.unsolved.count));
253
- const solvedCount = Math.abs(Math.trunc(this.captchaConfig.solved.count));
254
- if (!solvedCount) {
255
- throw new ProsopoEnvError('CONFIG.INVALID_CAPTCHA_NUMBER');
256
- }
257
- const solved = await this.getCaptchaWithProof(datasetId, true, solvedCount);
258
- let unsolved = [];
259
- if (unsolvedCount) {
260
- unsolved = await this.getCaptchaWithProof(datasetId, false, unsolvedCount);
261
- }
262
- const captchas = shuffleArray([...solved, ...unsolved]);
263
- const salt = randomAsHex();
264
- const requestHash = computePendingRequestHash(captchas.map((c) => c.captcha.captchaId), userAccount, salt);
265
- const currentTime = Date.now();
266
- const timeLimit = captchas.map((captcha) => captcha.captcha.timeLimitMs || 30000).reduce((a, b) => a + b, 0);
267
- const deadlineTs = timeLimit + currentTime;
268
- const currentBlockNumber = await getBlockNumber(this.contract.api);
269
- await this.db.storeDappUserPending(userAccount, requestHash, salt, deadlineTs, currentBlockNumber.toNumber());
270
- return { captchas, requestHash };
271
- }
272
- /**
273
- * Block by block search for blockNo
274
- */
275
- async isRecentBlock(contract, header, blockNo, depth = this.captchaSolutionConfig.captchaBlockRecency) {
276
- if (depth == 0) {
277
- return false;
278
- }
279
- const headerBlockNo = header.number.toPrimitive();
280
- if (headerBlockNo === blockNo) {
281
- return true;
282
- }
283
- const parent = await contract.api.rpc.chain.getBlock(header.parentHash);
284
- return this.isRecentBlock(contract, parent.block.header, blockNo, depth - 1);
285
- }
286
- /**
287
- * Validate that provided `datasetId` was a result of calling `get_random_provider` method
288
- * @param {string} userAccount - Same user that called `get_random_provider`
289
- * @param {string} dappContractAccount - account of dapp that is requesting captcha
290
- * @param {string} datasetId - `captcha_dataset_id` from the result of `get_random_provider`
291
- * @param {string} blockNumber - Block on which `get_random_provider` was called
292
- */
293
- async validateProviderWasRandomlyChosen(userAccount, dappContractAccount, datasetId, blockNumber) {
294
- const contract = await this.contract.contract;
295
- if (!contract) {
296
- throw new ProsopoEnvError('CONTRACT.CONTRACT_UNDEFINED', this.validateProviderWasRandomlyChosen.name);
297
- }
298
- const header = await contract.api.rpc.chain.getHeader();
299
- const isBlockNoValid = await this.isRecentBlock(contract, header, blockNumber);
300
- if (!isBlockNoValid) {
301
- throw new ProsopoEnvError('CAPTCHA.INVALID_BLOCK_NO', this.validateProviderWasRandomlyChosen.name, {}, {
302
- userAccount,
303
- dappContractAccount,
304
- datasetId,
305
- header,
306
- blockNumber,
307
- });
308
- }
309
- const block = (await contract.api.rpc.chain.getBlockHash(blockNumber));
310
- const randomProviderAndBlockNo = await this.contract.queryAtBlock(block, 'getRandomActiveProvider', [userAccount, dappContractAccount]);
311
- if (datasetId.toString().localeCompare(randomProviderAndBlockNo.provider.datasetId.toString())) {
312
- throw new ProsopoEnvError('DATASET.INVALID_DATASET_ID', this.validateProviderWasRandomlyChosen.name, {}, randomProviderAndBlockNo);
313
- }
314
- }
315
- /**
316
- * Get payment info for a transaction
317
- * @param {string} userAccount
318
- * @param {string} blockHash
319
- * @param {string} txHash
320
- * @returns {Promise<RuntimeDispatchInfo|null>}
321
- */
322
- async getPaymentInfo(userAccount, blockHash, txHash) {
323
- // Validate block and transaction, checking that the signer matches the userAccount
324
- const signedBlock = (await this.contract.api.rpc.chain.getBlock(blockHash));
325
- if (!signedBlock) {
326
- return null;
327
- }
328
- const extrinsic = signedBlock.block.extrinsics.find((extrinsic) => extrinsic.hash.toString() === txHash);
329
- if (!extrinsic || extrinsic.signer.toString() !== userAccount) {
330
- return null;
331
- }
332
- // Retrieve tx fee for extrinsic
333
- const paymentInfo = (await this.contract.api.rpc.payment.queryInfo(extrinsic.toHex(), blockHash));
334
- if (!paymentInfo) {
335
- return null;
336
- }
337
- return paymentInfo;
338
- }
339
- /*
340
- * Get dapp user solution from database
341
- */
342
- async getDappUserCommitmentById(commitmentId) {
343
- const dappUserSolution = await this.db.getDappUserCommitmentById(commitmentId);
344
- if (!dappUserSolution) {
345
- throw new ProsopoEnvError('CAPTCHA.DAPP_USER_SOLUTION_NOT_FOUND', this.getDappUserCommitmentById.name, {}, { commitmentId: commitmentId });
346
- }
347
- return dappUserSolution;
348
- }
349
- /* Check if dapp user has verified solution in cache */
350
- async getDappUserCommitmentByAccount(userAccount) {
351
- const dappUserSolutions = await this.db.getDappUserCommitmentByAccount(userAccount);
352
- if (dappUserSolutions.length > 0) {
353
- for (const dappUserSolution of dappUserSolutions) {
354
- if (dappUserSolution.status === ArgumentTypes.CaptchaStatus.approved) {
355
- return dappUserSolution;
356
- }
357
- }
358
- }
359
- return undefined;
360
- }
361
- /* Returns public details of provider */
362
- async getProviderDetails() {
363
- return await wrapQuery(this.contract.query.getProvider, this.contract.query)(this.contract.pair.address);
364
- }
365
- /** Get the dataset from the databse */
366
- async getProviderDataset(datasetId) {
367
- return await this.db.getDataset(datasetId);
368
- }
369
- }
370
- //# sourceMappingURL=tasks.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"tasks.js","sourceRoot":"","sources":["../../src/tasks/tasks.ts"],"names":[],"mappings":"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"}