]> zoso.dev Git - nano-pow.git/commitdiff
Complete conversion from threshold to difficulty.
authorChris Duncan <chris@zoso.dev>
Fri, 28 Mar 2025 04:27:35 +0000 (21:27 -0700)
committerChris Duncan <chris@zoso.dev>
Fri, 28 Mar 2025 04:27:35 +0000 (21:27 -0700)
README.md
docs/benchmarks.md
docs/nano-pow.1
src/bin/server.ts
src/lib/gl/gl-draw.frag
src/lib/gl/index.ts
src/lib/gpu/compute.wgsl
src/lib/gpu/index.ts
src/types.d.ts
test/index.html

index ba02a2a2c39096adfc1762d451a42e2d59cc61e4..fb13fb6fbe391197e8d867943c3bc0eacd75095d 100644 (file)
--- a/README.md
+++ b/README.md
@@ -76,9 +76,9 @@ const { valid } = await NanoPow.work_validate(work, hash)
 ```javascript
 const options = {
        // default 0xFFFFFFF800000000 for send/change blocks
-       threshold: number,
+       difficulty: 'FFFFFFC000000000',
        // default 8, valid range 1-32
-       effort: number,
+       effort: 16,
        // default false
        debug: true
 }
@@ -120,7 +120,7 @@ $ nano-pow --debug 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abc
 ```
 ```console
 $ # Generate work using customized behavior with options.
-$ nano-pow --effort 32 --threshold FFFFFFC000000000 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
+$ nano-pow --effort 32 --difficulty FFFFFFC000000000 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
 ```
 ```console
 $ # Validate an existing work nonce against a blockhash.
index e67591b52229995cb4f28fad89092d632b98d957..43c4cbcbd01b0d28cb11e5366ecc8d3ac57b6f3f 100644 (file)
@@ -4,7 +4,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
 -->
 
 # Benchmarks to compute 16,777,216 nonces
-_Each test is 128 samples of one pass (dispatch or frame) at zero threshold with no early exit_
+_Each test is 128 samples of one pass (dispatch or frame) at zero difficulty with no early exit_
 
 ## Summary
 - Chromium WebGPU and Firefox WebGL are the clear winners
index 2c0ff2bc8199437bb591f8ef80cd7e80809e56cf..ec4b5861391ca3eaba037683c68c412c2467dbc9 100644 (file)
@@ -37,7 +37,7 @@ Format final output of all hashes as a JSON array of stringified values instead
 \fB\-e\fR, \fB\-\-effort\fR=\fIEFFORT\fR
 Increase demand on GPU processing. Must be between 1 and 32 inclusive.
 .TP
-\fB\-t\fR, \fB\-\-threshold\fR=\fITHRESHOLD\fR
+\fB\-t\fR, \fB\-\-difficulty\fR=\fIDIFFICULTY\fR
 Override the minimum threshold value. Higher values increase difficulty. Must be a hexadecimal string between 1 and FFFFFFFFFFFFFFFF inclusive.
 .TP
 \fB\-v\fR, \fB\-\-validate\fR=\fIWORK\fR
@@ -89,13 +89,13 @@ Validate an existing work value against a blockhash. Requires \fBwork\fR field c
 
 .SH EXAMPLES - CLI
 .PP
-Search for a work nonce for a blockhash using the default threshold 0xFFFFFFF800000000:
+Search for a work nonce for a blockhash using the default difficulty 0xFFFFFFF800000000:
 .EX
 $ nano-pow \fB0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\fR
 .EE
 
 .PP
-Search for a work nonce using a custom threshold and increased effort:
+Search for a work nonce using a custom difficulty and increased effort:
 .EX
 $ nano-pow \fB\-t fffffe0000000000 \-e 32 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\fR
 .EE
index 7ae3bb497085d9cda015051d74ff18c7df4c1190..9bdaa7283c238837274aeee7c8c33f7ecefb6bbb 100755 (executable)
@@ -51,7 +51,7 @@ async function respond (res: http.ServerResponse, data: Buffer[]): Promise<void>
                const options: NanoPowOptions = {
                        debug: DEBUG,
                        effort: EFFORT,
-                       threshold: difficulty
+                       difficulty
                }
                const args = []
                if (work) args.push(work)
index bed53964b5c77255c93a73a3359156402c2540b7..f58c1a9ad9461841b85d29a7892a57d25711cf6f 100644 (file)
@@ -13,11 +13,11 @@ precision mediump float;
 out uvec4 nonce;
 
 // blockhash - Array of precalculated block hash components
-// threshold - 0xfffffff8 for send/change blocks, 0xfffffe00 for all else
+// difficulty - 0xfffffff800000000 for send/change blocks, 0xfffffe0000000000 for all else
 // validate - If true, checks only 1 pixel to validate, else checks all pixels to search
 layout(std140) uniform UBO {
        uint blockhash[8];
-       uvec2 threshold;
+       uvec2 difficulty;
        bool validate;
 };
 
@@ -228,7 +228,7 @@ void main() {
 
        // Pixel data set from work seed values
        uvec2 result = BLAKE2B_INIT[0u] ^ v[0u] ^ v[8u];
-       if ((validate && uvec2(gl_FragCoord) == uvec2(0u)) || (result.y > threshold.y || (result.y == threshold.y && result.x > threshold.x))) {
+       if ((validate && uvec2(gl_FragCoord) == uvec2(0u)) || (result.y > difficulty.y || (result.y == difficulty.y && result.x > difficulty.x))) {
                nonce = uvec4((BLAKE2B_INIT[0u] ^ v[0u] ^ v[8u]), m[0u]).yxwz;
        }
 
index 0c90c2d5b5ec3833cefe6659eb800ce8a16186bc..4d638b47db2b3fca46f5191a226b428a43e94e39 100644 (file)
@@ -369,16 +369,16 @@ export class NanoPowGl {
                if (this.#isInitialized === false) this.init()
                this.#busy = true
 
-               if (typeof options?.threshold === 'string') {
+               if (typeof options?.difficulty === 'string') {
                        try {
-                               options.threshold = BigInt(`0x${options.threshold}`)
+                               options.difficulty = BigInt(`0x${options.difficulty}`)
                        } catch (err) {
-                               throw new TypeError(`Invalid threshold ${options.threshold}`)
+                               throw new TypeError(`Invalid difficulty ${options.difficulty}`)
                        }
                }
-               const threshold = (typeof options?.threshold !== 'bigint' || options.threshold < 1n || options.threshold > 0xffffffffffffffffn)
+               const difficulty = (typeof options?.difficulty !== 'bigint' || options.difficulty < 1n || options.difficulty > 0xffffffffffffffffn)
                        ? 0xfffffff800000000n
-                       : options.threshold
+                       : options.difficulty
                const effort = (typeof options?.effort !== 'number' || options.effort < 0x1 || options.effort > 0x20)
                        ? this.#cores
                        : options.effort
@@ -409,7 +409,7 @@ export class NanoPowGl {
                        const uint32 = hash.slice(i, i + 8)
                        this.#uboView.setUint32(i * 2, parseInt(uint32, 16))
                }
-               this.#uboView.setBigUint64(128, threshold, true)
+               this.#uboView.setBigUint64(128, difficulty, true)
                this.#uboView.setUint32(136, 0, true)
                if (this.#debug) console.log('UBO', this.#uboView.buffer.slice(0))
                this.#gl.bindBuffer(this.#gl.UNIFORM_BUFFER, this.#uboBuffer)
@@ -469,16 +469,16 @@ export class NanoPowGl {
                if (this.#isInitialized === false) this.init()
                this.#busy = true
 
-               if (typeof options?.threshold === 'string') {
+               if (typeof options?.difficulty === 'string') {
                        try {
-                               options.threshold = BigInt(`0x${options.threshold}`)
+                               options.difficulty = BigInt(`0x${options.difficulty}`)
                        } catch (err) {
-                               throw new TypeError(`Invalid threshold ${options.threshold}`)
+                               throw new TypeError(`Invalid difficulty ${options.difficulty}`)
                        }
                }
-               const threshold = (typeof options?.threshold !== 'bigint' || options.threshold < 1n || options.threshold > 0xffffffffffffffffn)
+               const difficulty = (typeof options?.difficulty !== 'bigint' || options.difficulty < 1n || options.difficulty > 0xffffffffffffffffn)
                        ? 0xfffffff800000000n
-                       : options.threshold
+                       : options.difficulty
                this.#debug = !!(options?.debug)
                if (this.#debug) console.log('NanoPowGl.work_validate()')
                if (this.#debug) console.log('blockhash', hash)
@@ -499,7 +499,7 @@ export class NanoPowGl {
                        const uint32 = hash.slice(i, i + 8)
                        this.#uboView.setUint32(i * 2, parseInt(uint32, 16))
                }
-               this.#uboView.setBigUint64(128, threshold, true)
+               this.#uboView.setBigUint64(128, difficulty, true)
                this.#uboView.setUint32(136, 1, true)
                if (this.#debug) console.log('UBO', this.#uboView.buffer.slice(0))
                this.#gl.bindBuffer(this.#gl.UNIFORM_BUFFER, this.#uboBuffer)
@@ -532,7 +532,7 @@ export class NanoPowGl {
                        valid_all: (result >= this.#SEND) ? '1' : '0',
                        valid_receive: (result >= this.#RECEIVE) ? '1' : '0',
                }
-               if (options?.threshold != null) response.valid = (result >= threshold) ? '1' : '0'
+               if (options?.difficulty != null) response.valid = (result >= difficulty) ? '1' : '0'
                return response
        }
 }
index 3b0c7efb898461b410808352bb6e441b06581594..6a0ea13da5646ea9eea80be954950033b265506f 100644 (file)
@@ -7,7 +7,7 @@
 struct UBO {
        blockhash: array<vec4<u32>, 2>,
        seed: vec2<u32>,
-       threshold: vec2<u32>
+       difficulty: vec2<u32>
 };
 @group(0) @binding(0) var<uniform> ubo: UBO;
 
@@ -1659,11 +1659,10 @@ fn main(id: vec3<u32>, validate: bool) {
        ****************************************************************************/
 
        /**
-       * Set nonce if it passes the threshold and no other thread has set it.
-       * Only high bits are needed for comparison since threshold low bits are zero.
+       * Set nonce if it passes the difficulty threshold and no other thread has set it.
        */
        var result = BLAKE2B_INIT[0u] ^ v01.xy ^ v89.xy;
-       if (validate || ((result.y > ubo.threshold.y || (result.y == ubo.threshold.y && result.y >= ubo.threshold.y)) && atomicLoad(&work.found) == 0u)) {
+       if (validate || ((result.y > ubo.difficulty.y || (result.y == ubo.difficulty.y && result.y >= ubo.difficulty.y)) && atomicLoad(&work.found) == 0u)) {
                atomicStore(&work.found, 1u);
                work.nonce = m0;
                work.result = result;
index d46eba032d422f0d7e1a98ec67c5cace93fc81cb..067a1688eacce938b8c10f877eaacb5809be149c 100644 (file)
@@ -145,7 +145,7 @@ export class NanoPowGpu {
                console.table(averages)
        }
 
-       static async #dispatch (pipeline: GPUComputePipeline, seed: bigint, hash: string, threshold: bigint, passes: number): Promise<DataView> {
+       static async #dispatch (pipeline: GPUComputePipeline, seed: bigint, hash: string, difficulty: bigint, passes: number): Promise<DataView> {
                if (this.#device == null) throw new Error(`WebGPU device failed to load.`)
                // Set up uniform buffer object
                // Note: u32 size is 4, but total alignment must be multiple of 16
@@ -155,7 +155,7 @@ export class NanoPowGpu {
                        this.#uboView.setBigUint64(i / 2, BigInt(`0x${u64}`))
                }
                this.#uboView.setBigUint64(32, seed, true)
-               this.#uboView.setBigUint64(40, threshold, true)
+               this.#uboView.setBigUint64(40, difficulty, true)
                if (this.#debug) console.log('UBO', this.#uboView)
                this.#device.queue.writeBuffer(this.#uboBuffer, 0, this.#uboView)
 
@@ -207,7 +207,7 @@ export class NanoPowGpu {
                        this.#cpuBuffer.unmap()
                } catch (err) {
                        console.warn(`Error getting data from GPU. ${err}`)
-                       return this.#dispatch(pipeline, seed, hash, threshold, passes)
+                       return this.#dispatch(pipeline, seed, hash, difficulty, passes)
                }
                if (this.#debug) console.log('gpuBuffer data', data)
                if (data == null) throw new Error(`Failed to get data from buffer.`)
@@ -234,16 +234,16 @@ export class NanoPowGpu {
                if (this.#isInitialized === false) this.init()
                this.#busy = true
 
-               if (typeof options?.threshold === 'string') {
+               if (typeof options?.difficulty === 'string') {
                        try {
-                               options.threshold = BigInt(`0x${options.threshold}`)
+                               options.difficulty = BigInt(`0x${options.difficulty}`)
                        } catch (err) {
-                               throw new TypeError(`Invalid threshold ${options.threshold}`)
+                               throw new TypeError(`Invalid difficulty ${options.difficulty}`)
                        }
                }
-               const threshold = (typeof options?.threshold !== 'bigint' || options.threshold < 1n || options.threshold > 0xffffffffffffffffn)
+               const difficulty = (typeof options?.difficulty !== 'bigint' || options.difficulty < 1n || options.difficulty > 0xffffffffffffffffn)
                        ? 0xfffffff800000000n
-                       : options.threshold
+                       : options.difficulty
                const effort = (typeof options?.effort !== 'number' || options.effort < 0x1 || options.effort > 0x20)
                        ? 0x800
                        : options.effort * 0x100
@@ -274,7 +274,7 @@ export class NanoPowGpu {
                        const random1 = Math.floor(Math.random() * 0xffffffff)
                        const seed = (BigInt(random0) << 32n) | BigInt(random1)
                        if (this.#debug) console.log('seed', seed.toString(16).padStart(16, '0'))
-                       const data = await this.#dispatch(this.#searchPipeline, seed, hash, threshold, effort)
+                       const data = await this.#dispatch(this.#searchPipeline, seed, hash, difficulty, effort)
                        const found = !!data.getUint32(0)
                        nonce = data.getBigUint64(8, true)
                        result = data.getBigUint64(16, true)
@@ -313,16 +313,16 @@ export class NanoPowGpu {
                if (this.#isInitialized === false) this.init()
                this.#busy = true
 
-               if (typeof options?.threshold === 'string') {
+               if (typeof options?.difficulty === 'string') {
                        try {
-                               options.threshold = BigInt(`0x${options.threshold}`)
+                               options.difficulty = BigInt(`0x${options.difficulty}`)
                        } catch (err) {
-                               throw new TypeError(`Invalid threshold ${options.threshold}`)
+                               throw new TypeError(`Invalid difficulty ${options.difficulty}`)
                        }
                }
-               const threshold = (typeof options?.threshold !== 'bigint' || options.threshold < 1n || options.threshold > 0xffffffffffffffffn)
+               const difficulty = (typeof options?.difficulty !== 'bigint' || options.difficulty < 1n || options.difficulty > 0xffffffffffffffffn)
                        ? 0xfffffff800000000n
-                       : options.threshold
+                       : options.difficulty
                this.#debug = !!(options?.debug)
                if (this.#debug) console.log('NanoPowGpu.work_validate()')
                if (this.#debug) console.log('blockhash', hash)
@@ -345,7 +345,7 @@ export class NanoPowGpu {
 
                const seed = BigInt(`0x${work}`)
                if (this.#debug) console.log('work', work)
-               const data = await this.#dispatch(this.#validatePipeline, seed, hash, threshold, 1)
+               const data = await this.#dispatch(this.#validatePipeline, seed, hash, difficulty, 1)
                nonce = data.getBigUint64(8, true)
                result = data.getBigUint64(16, true)
                this.#busy = false
@@ -358,7 +358,7 @@ export class NanoPowGpu {
                        valid_all: (result >= this.#SEND) ? '1' : '0',
                        valid_receive: (result >= this.#RECEIVE) ? '1' : '0',
                }
-               if (options?.threshold != null) response.valid = (result >= threshold) ? '1' : '0'
+               if (options?.difficulty != null) response.valid = (result >= difficulty) ? '1' : '0'
                return response
        }
 }
index 2bffd006065476afeaa963fb9fabc4c7719a2791..2b81a7162b109106c7e95f47e4effd92f3d00b53 100644 (file)
@@ -99,12 +99,12 @@ export type FBO = {
 *
 * @param {boolean} [debug=false] - Enables additional debug logging to the console. Default: false
 * @param {number} [effort=0x8] - Multiplier for dispatching work search. Larger values are not necessarily better since they can quickly overwhelm the GPU. Ignored when validating. Default: 0x8
-* @param {bigint|string} [threshold=0xfffffff800000000] - Minimum value result of `BLAKE2b(nonce||blockhash)`. Default: 0xFFFFFFF800000000
+* @param {bigint|string} [difficulty=0xfffffff800000000] - Minimum value result of `BLAKE2b(nonce||blockhash)`. Default: 0xFFFFFFF800000000
 */
 export type NanoPowOptions = {
        debug?: boolean
        effort?: number
-       threshold?: bigint | string
+       difficulty?: bigint | string
 }
 
 /**
index 83d05f74bdac1b7e95f438e501ca7d162c022b55..a0a60567ebc498b8c7b31bd596140afd32b8c0fe 100644 (file)
@@ -69,7 +69,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
                        }
                }
 
-               export async function run (threshold, size, effort, isOutputShown, isGlForced, isDebug) {
+               export async function run (difficulty, size, effort, isOutputShown, isGlForced, isDebug) {
                        const NP = isGlForced ? NanoPowGl : NanoPow
                        const type = (NP === NanoPowGpu) ? 'WebGPU' : (NP === NanoPowGl) ? 'WebGL' : 'unknown API'
                        console.log(`%cNanoPow`, 'color:green', 'Checking validation against known values')
@@ -88,9 +88,9 @@ SPDX-License-Identifier: GPL-3.0-or-later
                        console.log(`work_validate() output for good nonce 2 is ${result === true ? 'correct' : 'incorrect'}`)
                        expect.push(result)
 
-                       result = await NP.work_validate('326f310d629a8a98', '204076E3364D16A018754FF67D418AB2FBEB38799FF9A29A1D5F9E34F16BEEEA', { threshold: 0xffffffff00000000n, debug: isDebug })
+                       result = await NP.work_validate('326f310d629a8a98', '204076E3364D16A018754FF67D418AB2FBEB38799FF9A29A1D5F9E34F16BEEEA', { difficulty: 0xffffffff00000000n, debug: isDebug })
                        result = result.valid === '1' && result.valid_all === '1' && result.valid_receive === '1'
-                       console.log(`work_validate() output for good max threshold nonce is ${result === true ? 'correct' : 'incorrect'}`)
+                       console.log(`work_validate() output for good max difficulty nonce is ${result === true ? 'correct' : 'incorrect'}`)
                        expect.push(result)
 
                        result = await NP.work_validate('c5d5d6f7c5d6ccd1', '281E89AC73B1082B464B9C3C1168384F846D39F6DF25105F8B4A22915E999117', { debug: isDebug })
@@ -98,9 +98,9 @@ SPDX-License-Identifier: GPL-3.0-or-later
                        console.log(`work_validate() output for colliding nonce is ${result === true ? 'correct' : 'incorrect'}`)
                        expect.push(result)
 
-                       result = await NP.work_validate('6866c1ac3831a891', '7069D9CD1E85D6204301D254B0927F06ACC794C9EA5DF70EA5578458FB597090', { threshold: 0xfffffe0000000000n, debug: isDebug })
+                       result = await NP.work_validate('6866c1ac3831a891', '7069D9CD1E85D6204301D254B0927F06ACC794C9EA5DF70EA5578458FB597090', { difficulty: 0xfffffe0000000000n, debug: isDebug })
                        result = result.valid === '1' && result.valid_all === '0' && result.valid_receive === '1'
-                       console.log(`work_validate() output for good receive threshold nonce is ${result === true ? 'correct' : 'incorrect'}`)
+                       console.log(`work_validate() output for good receive difficulty nonce is ${result === true ? 'correct' : 'incorrect'}`)
                        expect.push(result)
 
                        // XFAIL
@@ -114,9 +114,9 @@ SPDX-License-Identifier: GPL-3.0-or-later
                        console.log(`work_validate() output for bad nonce 2 is ${result === true ? 'correct' : 'incorrect'}`)
                        expect.push(result)
 
-                       result = await NP.work_validate('ae238556213c3624', 'BF41D87DA3057FDC6050D2B00C06531F89F4AA6195D7C6C2EAAF15B6E703F8F6', { threshold: 0xffffffff00000000n, debug: isDebug })
+                       result = await NP.work_validate('ae238556213c3624', 'BF41D87DA3057FDC6050D2B00C06531F89F4AA6195D7C6C2EAAF15B6E703F8F6', { difficulty: 0xffffffff00000000n, debug: isDebug })
                        result = result.valid === '0' && result.valid_all === '0' && result.valid_receive === '1'
-                       console.log(`work_validate() output for bad max threshold nonce is ${result === true ? 'correct' : 'incorrect'}`)
+                       console.log(`work_validate() output for bad max difficulty nonce is ${result === true ? 'correct' : 'incorrect'}`)
                        expect.push(result)
 
                        result = await NP.work_validate('29a9ae0236990e2e', '32721F4BD2AFB6F6A08D41CD0DF3C0D9C0B5294F68D0D12422F52B28F0800B5F', { debug: isDebug })
@@ -124,14 +124,14 @@ SPDX-License-Identifier: GPL-3.0-or-later
                        console.log(`work_validate() output for slightly wrong nonce is ${result === true ? 'correct' : 'incorrect'}`)
                        expect.push(result)
 
-                       result = await NP.work_validate('7d903b18d03f9820', '39C57C28F904DFE4012288FFF64CE80C0F42601023A9C82108E8F7B2D186C150', { threshold: 0xfffffe0000000000n, debug: isDebug })
+                       result = await NP.work_validate('7d903b18d03f9820', '39C57C28F904DFE4012288FFF64CE80C0F42601023A9C82108E8F7B2D186C150', { difficulty: 0xfffffe0000000000n, debug: isDebug })
                        result = result.valid === '0' && result.valid_all === '0' && result.valid_receive === '0'
-                       console.log(`work_validate() output for bad receive threshold nonce is ${result === true ? 'correct' : 'incorrect'}`)
+                       console.log(`work_validate() output for bad receive difficulty nonce is ${result === true ? 'correct' : 'incorrect'}`)
                        expect.push(result)
 
-                       result = await NP.work_validate('e45835c3b291c3d1', '9DCD89E2B92FD59D7358C2C2E4C225DF94C88E187B27882F50FEFC3760D3994F', { threshold: 0xffffffff00000000n, debug: isDebug })
+                       result = await NP.work_validate('e45835c3b291c3d1', '9DCD89E2B92FD59D7358C2C2E4C225DF94C88E187B27882F50FEFC3760D3994F', { difficulty: 0xffffffff00000000n, debug: isDebug })
                        result = result.valid === '0' && result.valid_all === '1' && result.valid_receive === '1'
-                       console.log(`work_validate() output for send threshold nonce that does not meet custom threshold is ${result === true ? 'correct' : 'incorrect'}`)
+                       console.log(`work_validate() output for send difficulty nonce that does not meet custom difficulty is ${result === true ? 'correct' : 'incorrect'}`)
                        expect.push(result)
 
                        try {
@@ -152,14 +152,14 @@ SPDX-License-Identifier: GPL-3.0-or-later
                                let result = null
                                const start = performance.now()
                                try {
-                                       result = await NP.work_generate(hash, { threshold, effort, debug: isDebug })
+                                       result = await NP.work_generate(hash, { difficulty, effort, debug: isDebug })
                                } catch (err) {
                                        document.getElementById('output').innerHTML += `Error: ${err.message}<br/>`
                                        console.error(err)
                                        return
                                }
                                const end = performance.now()
-                               const check = await NP.work_validate(result.work, result.hash, { threshold, debug: isDebug })
+                               const check = await NP.work_validate(result.work, result.hash, { difficulty, debug: isDebug })
                                const isValid = (result.hash === hash && check.valid === '1') ? 'VALID' : 'INVALID'
                                times.push(end - start)
                                const msg = `${isValid} [${result.work}] ${result.hash} (${end - start} ms)`
@@ -172,7 +172,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
                }
 
                function startValidation (event) {
-                       const threshold = document.getElementById('threshold')
+                       const difficulty = document.getElementById('difficulty')
                        const isGlForced = document.getElementById('isGlForced')
                        const work = document.getElementById('work')
                        const hash = document.getElementById('hash')
@@ -180,7 +180,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
                        validation.innerText = '⏳'
                        if (work.value.length === 16 && hash.value.length === 64) {
                                const NP = isGlForced ? NanoPowGl : NanoPow
-                               NP.work_validate(work.value, hash.value, { threshold: threshold.value })
+                               NP.work_validate(work.value, hash.value, { difficulty: difficulty.value })
                                        .then(result => {
                                                validation.innerText = result
                                                        ? '✔️'
@@ -191,18 +191,18 @@ SPDX-License-Identifier: GPL-3.0-or-later
                                        })
                        }
                }
-               document.getElementById('threshold').addEventListener('input', startValidation)
+               document.getElementById('difficulty').addEventListener('input', startValidation)
                document.getElementById('work').addEventListener('input', startValidation)
                document.getElementById('hash').addEventListener('input', startValidation)
 
                function startTest (event) {
-                       const threshold = document.getElementById('threshold')
+                       const difficulty = document.getElementById('difficulty')
                        const size = document.getElementById('size')
                        const effort = document.getElementById('effort')
                        const isOutputShown = document.getElementById('isOutputShown')
                        const isGlForced = document.getElementById('isGlForced')
                        const isDebug = document.getElementById('isDebug')
-                       run(threshold.value, +size.value, +effort.value, isOutputShown.checked, isGlForced.checked, isDebug.checked)
+                       run(difficulty.value, +size.value, +effort.value, isOutputShown.checked, isGlForced.checked, isDebug.checked)
                }
                document.getElementById('btnStartTest').addEventListener('click', startTest)
                document.getElementById('effort').value = Math.max(1, Math.floor(navigator.hardwareConcurrency))
@@ -223,8 +223,8 @@ SPDX-License-Identifier: GPL-3.0-or-later
        <p>Times below are in milliseconds and are summarized by various averaging methods.</p>
        <p>Level of Effort depends on hardware and does not guarantee faster results.</p>
        <hr />
-       <label for="threshold" class="hex">Threshold</label>
-       <input id="threshold" type="text" value="FFFFFFF800000000" />
+       <label for="difficulty" class="hex">Difficulty</label>
+       <input id="difficulty" type="text" value="FFFFFFF800000000" />
        <hr />
        <label for="work" class="hex">Validate Work</label>
        <input id="work" type="text" />