Merge pull request #16 from mCaptcha/feat-incremental
feat: incremental proof of work computing fn
This commit is contained in:
commit
b0111bde6e
2 changed files with 77 additions and 4 deletions
49
src/index.ts
49
src/index.ts
|
@ -4,7 +4,7 @@
|
|||
* Copyright © 2021 Aravinth Manivnanan <realaravinth@batsense.net>.
|
||||
*
|
||||
* Use of this source code is governed by Apache 2.0 or MIT license.
|
||||
* You shoud have received a copy of MIT and Apache 2.0 along with
|
||||
* You should have received a copy of MIT and Apache 2.0 along with
|
||||
* this program. If not, see <https://spdx.org/licenses/MIT.html> for
|
||||
* MIT or <http://www.apache.org/licenses/LICENSE-2.0> for Apache.
|
||||
*/
|
||||
|
@ -51,7 +51,7 @@ export const digest = async (message: string): Promise<number[]> => {
|
|||
* Calculate difficulty of a hash
|
||||
*
|
||||
* @param {number[]} hash - hash for which difficulty should be calculated
|
||||
* @returns {BigInt} - diffuclty of the given hash
|
||||
* @returns {BigInt} - difficulty of the given hash
|
||||
*/
|
||||
export const score = (hash: number[]): BigInt => {
|
||||
let sum = BigInt(0);
|
||||
|
@ -75,7 +75,7 @@ export type WasmWork = {
|
|||
};
|
||||
|
||||
/**
|
||||
* Generate Proof-of-Work(PoW) according to the algorithim used in mCaptcha
|
||||
* Generate Proof-of-Work(PoW) according to the algorithm used in mCaptcha
|
||||
*
|
||||
* @param {string} salt - salt used in PoW computation. Will be provided in PoW requirement
|
||||
* @param {string} phrase - challenge phrase used in PoW computation. Will be provided in PoW requirement
|
||||
|
@ -105,3 +105,46 @@ export const generate_work = async (
|
|||
};
|
||||
return work;
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate Proof-of-Work(PoW) according to the algorithm used in mCaptcha incrementally
|
||||
*
|
||||
* @param {string} salt - salt used in PoW computation. Will be provided in PoW requirement
|
||||
* @param {string} phrase - challenge phrase used in PoW computation. Will be provided in PoW requirement
|
||||
* @param {number} difficulty - target difficulty for which PoW should be generated. Will be provided in PoW requirement
|
||||
* @param {number} step - notify progress with nonce after 'n' number of steps
|
||||
* @param {(nonce: number) => void} fn - callback function to notify progress
|
||||
*
|
||||
* @returns {Promise<WasmWork>} - proof-of-work
|
||||
**/
|
||||
export const stepped_generate_work = async (
|
||||
salt: string,
|
||||
phrase: string,
|
||||
difficulty: number,
|
||||
step: number,
|
||||
fn: (nonce: number) => void,
|
||||
): Promise<WasmWork> => {
|
||||
const serialized_phrase = decoder.decode(serialize(phrase));
|
||||
const base = salt + serialized_phrase;
|
||||
let nonce = 0;
|
||||
let result: BigInt = BigInt(0);
|
||||
const difficulty_new: BigInt = U128_MAX - U128_MAX / BigInt(difficulty);
|
||||
let count = 0;
|
||||
while (result < difficulty_new) {
|
||||
if (count < step) {
|
||||
nonce += 1;
|
||||
const hash = await digest(base + nonce.toString());
|
||||
result = score(hash);
|
||||
count+=1;
|
||||
} else {
|
||||
fn(nonce);
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
const work: WasmWork = {
|
||||
result: result.toString(),
|
||||
nonce,
|
||||
};
|
||||
return work;
|
||||
};
|
||||
|
|
32
src/test.ts
32
src/test.ts
|
@ -1,4 +1,4 @@
|
|||
import { digest, score, generate_work } from "./index";
|
||||
import { digest, score, generate_work, stepped_generate_work } from "./index";
|
||||
import { DATA, DIFFICULTY, SALT } from "./test-data";
|
||||
|
||||
("use strict");
|
||||
|
@ -30,3 +30,33 @@ test("Digest works", async () => {
|
|||
}
|
||||
}
|
||||
});
|
||||
|
||||
test("Incremental proof generation works", async () => {
|
||||
for (let i = 0; i < DATA.length; i++) {
|
||||
const d = DATA[i];
|
||||
let last_nonce = 0;
|
||||
const step = 1000;
|
||||
let fnExecuted = false;
|
||||
const fn = (n: number): void => {
|
||||
expect(last_nonce + step).toBe(n);
|
||||
last_nonce = n;
|
||||
fnExecuted = true;
|
||||
};
|
||||
|
||||
try {
|
||||
const proof = await stepped_generate_work(
|
||||
SALT,
|
||||
d.phrase,
|
||||
DIFFICULTY,
|
||||
1000,
|
||||
fn
|
||||
);
|
||||
expect(proof.nonce).toBe(d.pow.nonce);
|
||||
expect(proof.result).toBe(`${d.pow.result}`);
|
||||
} catch (error) {
|
||||
console.log(`${d.pow.nonce}${error}`);
|
||||
throw error;
|
||||
}
|
||||
expect(fnExecuted).toBeTruthy();
|
||||
}
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue