From be7e76825c9e2d532f8724f79d55ed7784185cb2 Mon Sep 17 00:00:00 2001 From: Aravinth Manivannan Date: Sun, 29 Oct 2023 02:15:20 +0530 Subject: [PATCH] feat: incremental proof of work computing fn --- src/index.ts | 49 ++++++++++++++++++++++++++++++++++++++++++++++--- src/test.ts | 32 +++++++++++++++++++++++++++++++- 2 files changed, 77 insertions(+), 4 deletions(-) diff --git a/src/index.ts b/src/index.ts index 4a6e8d5..c73ebf2 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,7 +4,7 @@ * Copyright © 2021 Aravinth Manivnanan . * * 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 for * MIT or for Apache. */ @@ -51,7 +51,7 @@ export const digest = async (message: string): Promise => { * 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} - proof-of-work + **/ +export const stepped_generate_work = async ( + salt: string, + phrase: string, + difficulty: number, + step: number, + fn: (nonce: number) => void, +): Promise => { + 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; +}; diff --git a/src/test.ts b/src/test.ts index 2539fa5..40e2f96 100644 --- a/src/test.ts +++ b/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(); + } +});