From: Chris Duncan Date: Sun, 15 Dec 2024 07:48:34 +0000 (-0800) Subject: Define class members as private except for public find() function intended for enduser. X-Git-Url: https://zoso.dev/?a=commitdiff_plain;h=1bab06f8868ac782db494fc4e42a8184547b47ef;p=libnemo.git Define class members as private except for public find() function intended for enduser. --- diff --git a/src/lib/workers/pow.ts b/src/lib/workers/pow.ts index 27083b8..a8752ae 100644 --- a/src/lib/workers/pow.ts +++ b/src/lib/workers/pow.ts @@ -2,14 +2,13 @@ // SPDX-License-Identifier: GPL-3.0-or-later export class Pow { - /** * Finds a nonce that satisfies the Nano proof-of-work requirements. * * @param {string} hashHex - Hexadecimal hash of previous block, or public key for new accounts * @param {number} [threshold=0xfffffff8] - Difficulty of proof-of-work calculation */ - static async find (hash: string, threshold: number = this.SEND_THRESHOLD): Promise { + static async find (hash: string, threshold: number = 0xfffffff8): Promise { return new Promise(resolve => { this.#calculate(hash, resolve, threshold) }) @@ -22,7 +21,7 @@ export class Pow { * License: MIT */ // Vertext Shader - static vsSource = `#version 300 es + static #vsSource = `#version 300 es precision highp float; layout (location=0) in vec4 position; layout (location=1) in vec2 uv; @@ -35,7 +34,7 @@ void main() { }` // Fragment shader - static fsSource = `#version 300 es + static #fsSource = `#version 300 es precision highp float; precision highp int; @@ -199,12 +198,11 @@ void main() { } }` - static SEND_THRESHOLD = 0xFFFFFFF8 /** Used to set canvas size. Must be a multiple of 256. */ - static WORKLOAD: number = 256 * Math.max(1, Math.floor(navigator.hardwareConcurrency / 2)) - static work0 = new Uint8Array(4) - static work1 = new Uint8Array(4) - static SIGMA82: number[] = [ + static #WORKLOAD: number = 256 * Math.max(1, Math.floor(navigator.hardwareConcurrency / 2)) + static #work0 = new Uint8Array(4) + static #work1 = new Uint8Array(4) + static #SIGMA82: number[] = [ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 28, 20, 8, 16, 18, 30, 26, 12, 2, 24, 0, 4, 22, 14, 10, 6, 22, 16, 24, 0, 10, 4, 30, 26, 20, 28, 6, 12, 14, 2, 18, 8, 14, 18, 6, 2, 26, 24, 22, 28, 4, 12, 10, 20, 8, 0, 30, 16, 18, 0, 10, 14, 4, 8, 20, 30, 28, 2, 22, 24, 12, 16, 6, @@ -214,30 +212,29 @@ void main() { 26, 0, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 28, 20, 8, 16, 18, 30, 26, 12, 2, 24, 0, 4, 22, 14, 10, 6 ] - static B2B_G_params: number[] = [] + static #B2B_G_params: number[] = [] static { for (let i = 0; i < 12; i++) { - this.B2B_G_params.push(this.SIGMA82[i * 16 + 0]) - this.B2B_G_params.push(this.SIGMA82[i * 16 + 1]) - this.B2B_G_params.push(this.SIGMA82[i * 16 + 2]) - this.B2B_G_params.push(this.SIGMA82[i * 16 + 3]) - this.B2B_G_params.push(this.SIGMA82[i * 16 + 4]) - this.B2B_G_params.push(this.SIGMA82[i * 16 + 5]) - this.B2B_G_params.push(this.SIGMA82[i * 16 + 6]) - this.B2B_G_params.push(this.SIGMA82[i * 16 + 7]) - this.B2B_G_params.push(this.SIGMA82[i * 16 + 8]) - this.B2B_G_params.push(this.SIGMA82[i * 16 + 9]) - this.B2B_G_params.push(this.SIGMA82[i * 16 + 10]) - this.B2B_G_params.push(this.SIGMA82[i * 16 + 11]) - this.B2B_G_params.push(this.SIGMA82[i * 16 + 12]) - this.B2B_G_params.push(this.SIGMA82[i * 16 + 13]) - this.B2B_G_params.push(this.SIGMA82[i * 16 + 14]) - this.B2B_G_params.push(this.SIGMA82[i * 16 + 15]) + this.#B2B_G_params.push(this.#SIGMA82[i * 16 + 0]) + this.#B2B_G_params.push(this.#SIGMA82[i * 16 + 1]) + this.#B2B_G_params.push(this.#SIGMA82[i * 16 + 2]) + this.#B2B_G_params.push(this.#SIGMA82[i * 16 + 3]) + this.#B2B_G_params.push(this.#SIGMA82[i * 16 + 4]) + this.#B2B_G_params.push(this.#SIGMA82[i * 16 + 5]) + this.#B2B_G_params.push(this.#SIGMA82[i * 16 + 6]) + this.#B2B_G_params.push(this.#SIGMA82[i * 16 + 7]) + this.#B2B_G_params.push(this.#SIGMA82[i * 16 + 8]) + this.#B2B_G_params.push(this.#SIGMA82[i * 16 + 9]) + this.#B2B_G_params.push(this.#SIGMA82[i * 16 + 10]) + this.#B2B_G_params.push(this.#SIGMA82[i * 16 + 11]) + this.#B2B_G_params.push(this.#SIGMA82[i * 16 + 12]) + this.#B2B_G_params.push(this.#SIGMA82[i * 16 + 13]) + this.#B2B_G_params.push(this.#SIGMA82[i * 16 + 14]) + this.#B2B_G_params.push(this.#SIGMA82[i * 16 + 15]) } } - - static hexify (arr: number[] | Uint8Array): string { + static #hexify (arr: number[] | Uint8Array): string { let out = '' for (let i = arr.length - 1; i >= 0; i--) { out += arr[i].toString(16).padStart(2, '0') @@ -245,7 +242,7 @@ void main() { return out } - static processHash (hashHex: string): Uint32Array { + static #processHash (hashHex: string): Uint32Array { if (!/^[A-F-a-f0-9]{64}$/.test(hashHex)) { throw new Error(`invalid_hash ${hashHex}`) } @@ -264,105 +261,105 @@ void main() { B2B_G(0, 8, 16, 24, SIGMA82[i * 16 + 0], SIGMA82[i * 16 + 1]); */ - static gl: WebGL2RenderingContext | null - static program: WebGLProgram | null - static work0Location: WebGLUniformLocation | null - static work1Location: WebGLUniformLocation | null - static blockHashLocation: WebGLUniformLocation | null - static thresholdLocation: WebGLUniformLocation | null - static workloadLocation: WebGLUniformLocation | null - static vertexShader: WebGLShader | null - static fragmentShader: WebGLShader | null - static positionBuffer: WebGLBuffer | null - static uvBuffer: WebGLBuffer | null + static #gl: WebGL2RenderingContext | null + static #program: WebGLProgram | null + static #work0Location: WebGLUniformLocation | null + static #work1Location: WebGLUniformLocation | null + static #blockHashLocation: WebGLUniformLocation | null + static #thresholdLocation: WebGLUniformLocation | null + static #workloadLocation: WebGLUniformLocation | null + static #vertexShader: WebGLShader | null + static #fragmentShader: WebGLShader | null + static #positionBuffer: WebGLBuffer | null + static #uvBuffer: WebGLBuffer | null // Vertex Positions, 2 triangles - static positions = new Float32Array([ + static #positions = new Float32Array([ -1, -1, 0, -1, 1, 0, 1, 1, 0, 1, -1, 0, 1, 1, 0, -1, -1, 0 ]) // Texture Positions - static uvPosArray = new Float32Array([ + static #uvPosArray = new Float32Array([ 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1 ]) // Compile static { - this.gl = new OffscreenCanvas(this.WORKLOAD, this.WORKLOAD).getContext('webgl2') - if (this.gl == null) throw new Error('WebGL 2 is required') - - this.program = this.gl.createProgram() - if (this.program == null) throw new Error('Failed to create shader program') - - this.vertexShader = this.gl.createShader(this.gl.VERTEX_SHADER) - if (this.vertexShader == null) throw new Error('Failed to create vertex shader') - this.gl.shaderSource(this.vertexShader, this.vsSource) - this.gl.compileShader(this.vertexShader) - if (!this.gl.getShaderParameter(this.vertexShader, this.gl.COMPILE_STATUS)) - throw new Error(this.gl.getShaderInfoLog(this.vertexShader) ?? `Failed to compile vertex shader`) - - this.fragmentShader = this.gl.createShader(this.gl.FRAGMENT_SHADER) - if (this.fragmentShader == null) throw new Error('Failed to create fragment shader') - this.gl.shaderSource(this.fragmentShader, this.fsSource) - this.gl.compileShader(this.fragmentShader) - if (!this.gl.getShaderParameter(this.fragmentShader, this.gl.COMPILE_STATUS)) - throw new Error(this.gl.getShaderInfoLog(this.fragmentShader) ?? `Failed to compile fragment shader`) - - this.gl.attachShader(this.program, this.vertexShader) - this.gl.attachShader(this.program, this.fragmentShader) - this.gl.linkProgram(this.program) - if (!this.gl.getProgramParameter(this.program, this.gl.LINK_STATUS)) - throw new Error(this.gl.getProgramInfoLog(this.program) ?? `Failed to link program`) + this.#gl = new OffscreenCanvas(this.#WORKLOAD, this.#WORKLOAD).getContext('webgl2') + if (this.#gl == null) throw new Error('WebGL 2 is required') + + this.#program = this.#gl.createProgram() + if (this.#program == null) throw new Error('Failed to create shader program') + + this.#vertexShader = this.#gl.createShader(this.#gl.VERTEX_SHADER) + if (this.#vertexShader == null) throw new Error('Failed to create vertex shader') + this.#gl.shaderSource(this.#vertexShader, this.#vsSource) + this.#gl.compileShader(this.#vertexShader) + if (!this.#gl.getShaderParameter(this.#vertexShader, this.#gl.COMPILE_STATUS)) + throw new Error(this.#gl.getShaderInfoLog(this.#vertexShader) ?? `Failed to compile vertex shader`) + + this.#fragmentShader = this.#gl.createShader(this.#gl.FRAGMENT_SHADER) + if (this.#fragmentShader == null) throw new Error('Failed to create fragment shader') + this.#gl.shaderSource(this.#fragmentShader, this.#fsSource) + this.#gl.compileShader(this.#fragmentShader) + if (!this.#gl.getShaderParameter(this.#fragmentShader, this.#gl.COMPILE_STATUS)) + throw new Error(this.#gl.getShaderInfoLog(this.#fragmentShader) ?? `Failed to compile fragment shader`) + + this.#gl.attachShader(this.#program, this.#vertexShader) + this.#gl.attachShader(this.#program, this.#fragmentShader) + this.#gl.linkProgram(this.#program) + if (!this.#gl.getProgramParameter(this.#program, this.#gl.LINK_STATUS)) + throw new Error(this.#gl.getProgramInfoLog(this.#program) ?? `Failed to link program`) // Construct simple 2D geometry - this.gl.useProgram(this.program) - const triangleArray = this.gl.createVertexArray() - this.gl.bindVertexArray(triangleArray) - - this.positionBuffer = this.gl.createBuffer() - this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.positionBuffer) - this.gl.bufferData(this.gl.ARRAY_BUFFER, this.positions, this.gl.STATIC_DRAW) - this.gl.vertexAttribPointer(0, 3, this.gl.FLOAT, false, 0, 0) - this.gl.enableVertexAttribArray(0) - - const uvBuffer = this.gl.createBuffer() - this.gl.bindBuffer(this.gl.ARRAY_BUFFER, uvBuffer) - this.gl.bufferData(this.gl.ARRAY_BUFFER, this.uvPosArray, this.gl.STATIC_DRAW) - this.gl.vertexAttribPointer(1, 2, this.gl.FLOAT, false, 0, 0) - this.gl.enableVertexAttribArray(1) - - this.work0Location = this.gl.getUniformLocation(this.program, 'u_work0') - this.work1Location = this.gl.getUniformLocation(this.program, 'u_work1') - this.blockHashLocation = this.gl.getUniformLocation(this.program, "blockHash") - this.thresholdLocation = this.gl.getUniformLocation(this.program, "threshold") - this.workloadLocation = this.gl.getUniformLocation(this.program, "workload") + this.#gl.useProgram(this.#program) + const triangleArray = this.#gl.createVertexArray() + this.#gl.bindVertexArray(triangleArray) + + this.#positionBuffer = this.#gl.createBuffer() + this.#gl.bindBuffer(this.#gl.ARRAY_BUFFER, this.#positionBuffer) + this.#gl.bufferData(this.#gl.ARRAY_BUFFER, this.#positions, this.#gl.STATIC_DRAW) + this.#gl.vertexAttribPointer(0, 3, this.#gl.FLOAT, false, 0, 0) + this.#gl.enableVertexAttribArray(0) + + this.#uvBuffer = this.#gl.createBuffer() + this.#gl.bindBuffer(this.#gl.ARRAY_BUFFER, this.#uvBuffer) + this.#gl.bufferData(this.#gl.ARRAY_BUFFER, this.#uvPosArray, this.#gl.STATIC_DRAW) + this.#gl.vertexAttribPointer(1, 2, this.#gl.FLOAT, false, 0, 0) + this.#gl.enableVertexAttribArray(1) + + this.#work0Location = this.#gl.getUniformLocation(this.#program, 'u_work0') + this.#work1Location = this.#gl.getUniformLocation(this.#program, 'u_work1') + this.#blockHashLocation = this.#gl.getUniformLocation(this.#program, "blockHash") + this.#thresholdLocation = this.#gl.getUniformLocation(this.#program, "threshold") + this.#workloadLocation = this.#gl.getUniformLocation(this.#program, "workload") } - static #calculate (hashHex: string, callback: (nonce: string | PromiseLike) => any, threshold: number = this.SEND_THRESHOLD): void { + static #calculate (hashHex: string, callback: (nonce: string | PromiseLike) => any, threshold: number): void { if (typeof threshold !== 'number') throw new TypeError(`Invalid threshold ${threshold}`) - if (this.gl == null) throw new Error('WebGL 2 is required') - this.gl.clearColor(0, 0, 0, 1) - const hashBytes: Uint32Array = this.processHash(hashHex) + if (this.#gl == null) throw new Error('WebGL 2 is required') + this.#gl.clearColor(0, 0, 0, 1) + const hashBytes: Uint32Array = this.#processHash(hashHex) // Draw output until success or progressCallback says to stop let n = 0 const frameTimes: number[] = [] const draw = (): void => { n++ - if (Pow.gl == null) throw new Error('webgl2_required') + if (Pow.#gl == null) throw new Error('WebGL 2 is required') performance.mark('start') - crypto.getRandomValues(Pow.work0) - crypto.getRandomValues(Pow.work1) - - Pow.gl.uniform4uiv(Pow.work0Location, this.work0) - Pow.gl.uniform4uiv(Pow.work1Location, this.work1) - Pow.gl.uniform1uiv(Pow.blockHashLocation, hashBytes) - Pow.gl.uniform1ui(Pow.thresholdLocation, threshold) - Pow.gl.uniform1f(Pow.workloadLocation, this.WORKLOAD - 1) - - Pow.gl.clear(Pow.gl.COLOR_BUFFER_BIT) - Pow.gl.drawArrays(Pow.gl.TRIANGLES, 0, 6) - const pixels = new Uint8Array(Pow.gl.drawingBufferWidth * Pow.gl.drawingBufferHeight * 4) - Pow.gl.readPixels(0, 0, Pow.gl.drawingBufferWidth, Pow.gl.drawingBufferHeight, Pow.gl.RGBA, Pow.gl.UNSIGNED_BYTE, pixels) + crypto.getRandomValues(Pow.#work0) + crypto.getRandomValues(Pow.#work1) + + Pow.#gl.uniform4uiv(Pow.#work0Location, this.#work0) + Pow.#gl.uniform4uiv(Pow.#work1Location, this.#work1) + Pow.#gl.uniform1uiv(Pow.#blockHashLocation, hashBytes) + Pow.#gl.uniform1ui(Pow.#thresholdLocation, threshold) + Pow.#gl.uniform1f(Pow.#workloadLocation, this.#WORKLOAD - 1) + + Pow.#gl.clear(Pow.#gl.COLOR_BUFFER_BIT) + Pow.#gl.drawArrays(Pow.#gl.TRIANGLES, 0, 6) + const pixels = new Uint8Array(Pow.#gl.drawingBufferWidth * Pow.#gl.drawingBufferHeight * 4) + Pow.#gl.readPixels(0, 0, Pow.#gl.drawingBufferWidth, Pow.#gl.drawingBufferHeight, Pow.#gl.RGBA, Pow.#gl.UNSIGNED_BYTE, pixels) // Check the pixels for any success for (let i = 0; i < pixels.length; i += 4) { if (pixels[i] !== 0) { @@ -371,11 +368,11 @@ void main() { performance.clearMarks() console.log(`average frame time: ${(frameTimes.reduce((a, b) => a + b)) / frameTimes.length} ms`) console.log(`frames calculated: ${n}`) - const hex = this.hexify(this.work1) + this.hexify([ + const hex = this.#hexify(this.#work1) + this.#hexify([ pixels[i + 2], pixels[i + 3], - this.work0[2] ^ (pixels[i] - 1), - this.work0[3] ^ (pixels[i + 1] - 1) + this.#work0[2] ^ (pixels[i] - 1), + this.#work0[3] ^ (pixels[i + 1] - 1) ]) // Return the work value with the custom bits typeof callback === 'function' && callback(hex)