import { launch } from 'puppeteer'
import { subtle } from 'node:crypto'
-import { readFile, unlink, writeFile } from 'node:fs/promises'
+import { readFile } from 'node:fs/promises'
import * as http from 'node:http'
-import { AddressInfo } from 'node:net'
+import { AddressInfo, Socket } from 'node:net'
import { homedir } from 'node:os'
import { join } from 'node:path'
import type { NanoPowOptions, WorkGenerateRequest, WorkGenerateResponse, WorkValidateRequest, WorkValidateResponse } from '#types'
*/
function log (...args: any[]): void {
if (CONFIG.DEBUG) {
- const d = new Date(Date.now())
- const opts: Intl.DateTimeFormatOptions = {
- hour12: false,
- dateStyle: 'medium',
- timeStyle: 'medium'
- }
- console.log(d.toLocaleString(navigator.language, opts), `NanoPow[${process.pid}]:`, args)
+ const text = `${new Date(Date.now()).toLocaleString(Intl.DateTimeFormat().resolvedOptions().locale ?? 'en-US', { hour12: false, dateStyle: 'medium', timeStyle: 'medium' })} NanoPow[${process.pid}]: ${args}`
+ console.log(text)
+ process.send?.({ type: 'console', text })
}
}
process.title = 'NanoPow Server'
+const MAX_BODY_SIZE = 256
+const MAX_CONNECTIONS = 1024
+const MAX_HEADER_COUNT = 32
+const MAX_IDLE_TIME = 5000
+const MAX_REQUEST_COUNT = 10
const MAX_REQUEST_SIZE = 1024
-const MAX_BODY_SIZE = 158
+const MAX_REQUEST_TIME = 60000
+
+const requests: Map<string, { tokens: number, time: number }> = new Map()
+setInterval(() => {
+ for (const [i, t] of requests) {
+ if (t.time < Date.now() - MAX_REQUEST_TIME) {
+ requests.delete(i)
+ }
+ }
+}, Math.max(MAX_REQUEST_TIME, 0))
const CONFIG = {
DEBUG: false,
await loadConfig()
})
-async function respond (res: http.ServerResponse, data: Buffer[]): Promise<void> {
+async function respond (res: http.ServerResponse, dataBuffer: Buffer[]): Promise<void> {
let statusCode: number = 500
let headers: http.OutgoingHttpHeaders = { 'Content-Type': 'application/json' }
- let response: string = 'work_validate failed'
+ let response: string = 'request failed'
try {
- const datastring = Buffer.concat(data).toString().replace(/\s+/g, '')
+ const datastring = Buffer.concat(dataBuffer).toString()
if (Buffer.byteLength(datastring) > MAX_BODY_SIZE) {
- throw new Error('Invalid data.')
+ throw new Error('Data too large.')
}
- const { action, hash, work, difficulty }: WorkGenerateRequest | WorkValidateRequest = JSON.parse(datastring)
+ const data: WorkGenerateRequest | WorkValidateRequest = JSON.parse(datastring)
+ if (Object.getPrototypeOf(data) !== Object.prototype) {
+ throw new Error('Data corrupted.')
+ }
+ const { action, hash, work, difficulty } = data
if (action !== 'work_generate' && action !== 'work_validate') {
- throw new Error('Invalid action. Must be work_generate or work_validate.')
+ throw new Error('Action must be work_generate or work_validate.')
}
+ response = `${action} failed`
if (!/^[0-9A-Fa-f]{64}$/.test(hash ?? '')) {
- throw new Error('Invalid hash. Must be a 64-character hex string.')
+ throw new Error('Hash must be a 64-character hex string.')
}
- if (difficulty && !/^[1-9A-Fa-f][0-9A-Fa-f]{0,15}$/.test(difficulty)) {
- throw new Error('Invalid difficulty. Must be a hexadecimal string between 1-FFFFFFFFFFFFFFFF.')
+ if (difficulty && !/^[0-9A-Fa-f]{0,16}$/.test(difficulty)) {
+ throw new Error('Difficulty must be a hex string between 0-FFFFFFFFFFFFFFFF.')
}
if (action === 'work_validate' && !/^[0-9A-Fa-f]{16}$/.test(work ?? '')) {
- throw new Error('Invalid work. Must be a 16-character hex string.')
+ throw new Error('Work must be a 16-character hex string.')
}
- response = `${action} failed`
const options: NanoPowOptions = {
debug: CONFIG.DEBUG,
effort: CONFIG.EFFORT,
difficulty
}
- const args = []
- if (work) args.push(work)
- args.push(hash)
- args.push(options)
- response = JSON.stringify(await page.evaluate(async (action: string, args: (string | NanoPowOptions)[]): Promise<WorkGenerateResponse | WorkValidateResponse> => {
- if (window.NanoPow == null) throw new Error('NanoPow not found')
- return await window.NanoPow[action](...args)
- }, action, args))
+ switch (action) {
+ case ('work_generate'): {
+ response = JSON.stringify(await page.evaluate(async (np, hash: string, options: NanoPowOptions): Promise<WorkGenerateResponse | WorkValidateResponse> => {
+ if (np == null) throw new Error('NanoPow not found')
+ return await np.work_generate(hash, options)
+ }, npHandle, hash, options))
+ break
+ }
+ case ('work_validate'): {
+ response = JSON.stringify(await page.evaluate(async (np, work: string, hash: string, options: NanoPowOptions): Promise<WorkGenerateResponse | WorkValidateResponse> => {
+ if (np == null) throw new Error('NanoPow not found')
+ return await np.work_validate(work, hash, options)
+ }, npHandle, work, hash, options))
+ break
+ }
+ default: {
+ throw new Error('Action must be work_generate or work_validate.')
+ }
+ }
statusCode = 200
} catch (err) {
log(err)
// Create server
const server = http.createServer((req, res): void => {
+ const xff = req.headers['x-forwarded-for']
+ const ip = (typeof xff === 'string')
+ ? xff.split(',')[0].trim().replace(/^::ffff:/, '')
+ : req.socket.remoteAddress
+ if (ip == null) {
+ res.writeHead(401).end('Unauthorized')
+ return
+ }
+ const client = requests.get(ip)
+ if (ip === '127.0.0.1' || process.send != null || client == null || client.time < Date.now() - MAX_REQUEST_TIME) {
+ requests.set(ip, { tokens: MAX_REQUEST_COUNT, time: Date.now() })
+ } else {
+ if (--client.tokens <= 0) {
+ log(`${ip} potential abuse`)
+ res.writeHead(429).end('Too Many Requests')
+ return
+ }
+ }
let data: Buffer[] = []
let reqSize = 0
if (req.method === 'POST') {
+ const contentLength = +(req.headers['content-length'] ?? 0)
+ if (contentLength == 0 || contentLength > MAX_BODY_SIZE) {
+ res.writeHead(413).end('Content Too Large')
+ req.socket.destroy()
+ return
+ }
req.on('data', (chunk: Buffer): void => {
reqSize += chunk.byteLength
if (reqSize > MAX_REQUEST_SIZE) {
- res.writeHead(413, { 'Content-Type': 'text/plain' })
- res.end('Content Too Large')
+ res.writeHead(413).end('Content Too Large')
req.socket.destroy()
return
}
}
})
-server.on('error', (e): void => {
+server.headersTimeout = MAX_IDLE_TIME
+server.keepAliveTimeout = MAX_IDLE_TIME
+server.maxConnections = MAX_CONNECTIONS
+server.maxHeadersCount = MAX_HEADER_COUNT
+
+server.on('connection', (c: Socket): void => {
+ c.setTimeout(MAX_IDLE_TIME, () => c.destroy())
+})
+
+server.on('error', (e: Error): void => {
log('Server error', e)
try {
shutdown()
headless: true,
args: [
'--headless=new',
- '--use-angle=vulkan',
- '--enable-features=Vulkan',
'--disable-vulkan-surface',
+ '--enable-features=Vulkan,DefaultANGLEVulkan,VulkanFromANGLE',
+ '--enable-gpu',
'--enable-unsafe-webgpu'
]
})
const page = await browser.newPage()
-page.on('console', msg => log(msg.text()))
-const path: string = new URL(import.meta.url).pathname
-const dir = path.slice(0, path.lastIndexOf('/'))
-const filename = join(dir, `${process.pid}.html`)
-await writeFile(filename, '<!DOCTYPE html><link rel="icon" href="data:,">')
-await page.goto(import.meta.resolve(filename))
-await page.waitForFunction(async (): Promise<GPUAdapter | null> => {
- return await navigator['gpu'].requestAdapter()
-})
-
-const src = `${NanoPow};window.NanoPow=NanoPow;`
+const src = `${NanoPow};window.NanoPow=NanoPowGpu;`
const hash = await subtle.digest('SHA-256', Buffer.from(src))
const enc = `sha256-${Buffer.from(hash).toString('base64')}`
-
-await page.setContent(`
+const body = `
<!DOCTYPE html>
<link rel="icon" href="data:,">
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; base-uri 'none'; form-action 'none'; script-src '${enc}';">
<script type="module">${src}</script>
-`)
-await unlink(filename)
+`
+
+await page.setRequestInterception(true)
+page.on('request', async (req): Promise<void> => {
+ if (req.isInterceptResolutionHandled()) return
+ if (req.url() === 'https://nanopow.invalid/') {
+ req.respond({ status: 200, contentType: 'text/html', body })
+ } else {
+ req.continue()
+ }
+})
+page.on('console', msg => log(msg.text()))
+await page.goto('https://nanopow.invalid/')
+await page.waitForFunction(async (): Promise<boolean> => {
+ return window.NanoPow != null
+})
+const npHandle = await page.evaluateHandle(() => window.NanoPow)
+
log('Puppeteer initialized')
// Listen on configured port
-server.listen(CONFIG.PORT, async (): Promise<void> => {
+server.listen(CONFIG.PORT, '127.0.0.1', async (): Promise<void> => {
const { port } = server.address() as AddressInfo
CONFIG.PORT = port
log(`Server listening on port ${port}`)
/**
* Search compute function
-* Calls main with a workgroup size of 96 which in testing was the lowest value
-* that would saturate the GPU active thread count and warp occupancy which
-* provides a decent balance with the power-sensitive requirements of mobile
+* Calls main with a workgroup size of 64 which balances warps between NVIDIA and
+* AMD cards while still considering the power-sensitive requirements of mobile
* devices. The entire workgroup exits immediately if a nonce was already found
* by a previous workgroup.
*/
-@compute @workgroup_size(96)
+@compute @workgroup_size(64)
fn search(@builtin(global_invocation_id) global_id: vec3<u32>, @builtin(local_invocation_id) local_id: vec3<u32>) {
if (local_id.x == 0u) {
found = atomicLoad(&work.found) != 0u;
* due to the lack of both a native rotate function and 64-bit support in WGSL.
*/
- /****************************************************************************
- * ROUND(0) *
- ****************************************************************************/
-
/**
- * r=0, i=0, a=v[0], b=v[4], c=v[8], d=v[12], m[sigma]=0, m[sigma+1]=1
- * r=0, i=1, a=v[1], b=v[5], c=v[9], d=v[13], m[sigma]=2, m[sigma+1]=3
- * r=0, i=2, a=v[2], b=v[6], c=v[10], d=v[14], m[sigma]=4, m[sigma+1]=5
- * r=0, i=3, a=v[3], b=v[7], c=v[11], d=v[15], m[sigma]=6, m[sigma+1]=7
+ * ROUND(0)
+ * m[sigma]=(0,1),(2,3),(4,5),(6,7)
+ * m[sigma]=(8,9),(10,11),(12,13),(14,15)
*/
G(&v0, &v4, &v8, &vC, m0, m1);
G(&v1, &v5, &v9, &vD, m2, m3);
G(&v2, &v6, &vA, &vE, m4, Z);
G(&v3, &v7, &vB, &vF, Z, Z);
- /**
- * r=0, i=4, a=v[0], b=v[5], c=v[10], d=v[15], m[sigma]=8, m[sigma+1]=9
- * r=0, i=5, a=v[1], b=v[6], c=v[11], d=v[12], m[sigma]=10, m[sigma+1]=11
- * r=0, i=6, a=v[2], b=v[7], c=v[8], d=v[13], m[sigma]=12, m[sigma+1]=13
- * r=0, i=7, a=v[3], b=v[4], c=v[9], d=v[14], m[sigma]=14, m[sigma+1]=15
- */
G(&v0, &v5, &vA, &vF, Z, Z);
G(&v1, &v6, &vB, &vC, Z, Z);
G(&v2, &v7, &v8, &vD, Z, Z);
G(&v3, &v4, &v9, &vE, Z, Z);
- /****************************************************************************
- * ROUND(1) *
- ****************************************************************************/
-
/**
- * r=1, i=0, a=v[0], b=v[4], c=v[8], d=v[12], m[sigma]=14, m[sigma+1]=10
- * r=1, i=1, a=v[1], b=v[5], c=v[9], d=v[13], m[sigma]=4, m[sigma+1]=8
- * r=1, i=2, a=v[2], b=v[6], c=v[10], d=v[14], m[sigma]=9, m[sigma+1]=15
- * r=1, i=3, a=v[3], b=v[7], c=v[11], d=v[15], m[sigma]=13, m[sigma+1]=6
+ * ROUND(1)
+ * m[sigma]=(14,10),(4,8),(9,15),(13,6)
+ * m[sigma]=(1,12),(0,2),(11,7),(5,3)
*/
G(&v0, &v4, &v8, &vC, Z, Z);
G(&v1, &v5, &v9, &vD, m4, Z);
G(&v2, &v6, &vA, &vE, Z, Z);
G(&v3, &v7, &vB, &vF, Z, Z);
- /**
- * r=1, i=4, a=v[0], b=v[5], c=v[10], d=v[15], m[sigma]=1, m[sigma+1]=12
- * r=1, i=5, a=v[1], b=v[6], c=v[11], d=v[12], m[sigma]=0, m[sigma+1]=2
- * r=1, i=6, a=v[2], b=v[7], c=v[8], d=v[13], m[sigma]=11, m[sigma+1]=7
- * r=1, i=7, a=v[3], b=v[4], c=v[9], d=v[14], m[sigma]=5, m[sigma+1]=3
- */
G(&v0, &v5, &vA, &vF, m1, Z);
G(&v1, &v6, &vB, &vC, m0, m2);
G(&v2, &v7, &v8, &vD, Z, Z);
G(&v3, &v4, &v9, &vE, Z, m3);
- /****************************************************************************
- * ROUND(2) *
- ****************************************************************************/
-
/**
- * r=2, i=0, a=v[0], b=v[4], c=v[8], d=v[12], m[sigma]=11, m[sigma+1]=8
- * r=2, i=1, a=v[1], b=v[5], c=v[9], d=v[13], m[sigma]=12, m[sigma+1]=0
- * r=2, i=2, a=v[2], b=v[6], c=v[10], d=v[14], m[sigma]=5, m[sigma+1]=2
- * r=2, i=3, a=v[3], b=v[7], c=v[11], d=v[15], m[sigma]=15, m[sigma+1]=13
+ * ROUND(2)
+ * m[sigma]=(11,8),(12,0),(5,2),(15,13)
+ * m[sigma]=(10,14),(3,6),(7,1),(9,4)
*/
G(&v0, &v4, &v8, &vC, Z, Z);
G(&v1, &v5, &v9, &vD, Z, m0);
G(&v2, &v6, &vA, &vE, Z, m2);
G(&v3, &v7, &vB, &vF, Z, Z);
- /**
- * r=2, i=4, a=v[0], b=v[5], c=v[10], d=v[15], m[sigma]=10, m[sigma+1]=14
- * r=2, i=5, a=v[1], b=v[6], c=v[11], d=v[12], m[sigma]=3, m[sigma+1]=6
- * r=2, i=6, a=v[2], b=v[7], c=v[8], d=v[13], m[sigma]=7, m[sigma+1]=1
- * r=2, i=7, a=v[3], b=v[4], c=v[9], d=v[14], m[sigma]=9, m[sigma+1]=4
- */
G(&v0, &v5, &vA, &vF, Z, Z);
G(&v1, &v6, &vB, &vC, m3, Z);
G(&v2, &v7, &v8, &vD, Z, m1);
G(&v3, &v4, &v9, &vE, Z, m4);
- /****************************************************************************
- * ROUND(3) *
- ****************************************************************************/
-
/**
- * r=3, i=0, a=v[0], b=v[4], c=v[8], d=v[12], m[sigma]=7, m[sigma+1]=9
- * r=3, i=1, a=v[1], b=v[5], c=v[9], d=v[13], m[sigma]=3, m[sigma+1]=1
- * r=3, i=2, a=v[2], b=v[6], c=v[10], d=v[14], m[sigma]=13, m[sigma+1]=12
- * r=3, i=3, a=v[3], b=v[7], c=v[11], d=v[15], m[sigma]=11, m[sigma+1]=14
+ * ROUND(3)
+ * m[sigma]=(7,9),(3,1),(13,12),(11,14)
+ * m[sigma]=(2,6),(5,10),(4,0),(15,8)
*/
G(&v0, &v4, &v8, &vC, Z, Z);
G(&v1, &v5, &v9, &vD, m3, m1);
G(&v2, &v6, &vA, &vE, Z, Z);
G(&v3, &v7, &vB, &vF, Z, Z);
- /**
- * r=3, i=4, a=v[0], b=v[5], c=v[10], d=v[15], m[sigma]=2, m[sigma+1]=6
- * r=3, i=5, a=v[1], b=v[6], c=v[11], d=v[12], m[sigma]=5, m[sigma+1]=10
- * r=3, i=6, a=v[2], b=v[7], c=v[8], d=v[13], m[sigma]=4, m[sigma+1]=0
- * r=3, i=7, a=v[3], b=v[4], c=v[9], d=v[14], m[sigma]=15, m[sigma+1]=8
- */
G(&v0, &v5, &vA, &vF, m2, Z);
G(&v1, &v6, &vB, &vC, Z, Z);
G(&v2, &v7, &v8, &vD, m4, m0);
G(&v3, &v4, &v9, &vE, Z, Z);
- /****************************************************************************
- * ROUND(4) *
- ****************************************************************************/
-
/**
- * r=4, i=0, a=v[0], b=v[4], c=v[8], d=v[12], m[sigma]=9, m[sigma+1]=0
- * r=4, i=1, a=v[1], b=v[5], c=v[9], d=v[13], m[sigma]=5, m[sigma+1]=7
- * r=4, i=2, a=v[2], b=v[6], c=v[10], d=v[14], m[sigma]=2, m[sigma+1]=4
- * r=4, i=3, a=v[3], b=v[7], c=v[11], d=v[15], m[sigma]=10, m[sigma+1]=15
+ * ROUND(4)
+ * m[sigma]=(9,0),(5,7),(2,4),(10,15)
+ * m[sigma]=(14,1),(11,12),(6,8),(3,13)
*/
G(&v0, &v4, &v8, &vC, Z, m0);
G(&v1, &v5, &v9, &vD, Z, Z);
G(&v2, &v6, &vA, &vE, m2, m4);
G(&v3, &v7, &vB, &vF, Z, Z);
- /**
- */
-
- /**
- * r=4, i=4, a=v[0], b=v[5], c=v[10], d=v[15], m[sigma]=14, m[sigma+1]=1
- * r=4, i=5, a=v[1], b=v[6], c=v[11], d=v[12], m[sigma]=11, m[sigma+1]=12
- * r=4, i=6, a=v[2], b=v[7], c=v[8], d=v[13], m[sigma]=6, m[sigma+1]=8
- * r=4, i=7, a=v[3], b=v[4], c=v[9], d=v[14], m[sigma]=3, m[sigma+1]=13
- */
G(&v0, &v5, &vA, &vF, Z, m1);
G(&v1, &v6, &vB, &vC, Z, Z);
G(&v2, &v7, &v8, &vD, Z, Z);
G(&v3, &v4, &v9, &vE, m3, Z);
- /****************************************************************************
- * ROUND(5) *
- ****************************************************************************/
-
/**
- * r=5, i=0, a=v[0], b=v[4], c=v[8], d=v[12], m[sigma]=2, m[sigma+1]=12
- * r=5, i=1, a=v[1], b=v[5], c=v[9], d=v[13], m[sigma]=6, m[sigma+1]=10
- * r=5, i=2, a=v[2], b=v[6], c=v[10], d=v[14], m[sigma]=0, m[sigma+1]=11
- * r=5, i=3, a=v[3], b=v[7], c=v[11], d=v[15], m[sigma]=8, m[sigma+1]=3
+ * ROUND(5)
+ * m[sigma]=(2,12),(6,10),(0,11),(8,3)
+ * m[sigma]=(4,13),(7,5),(15,14),(1,9)
*/
G(&v0, &v4, &v8, &vC, m2, Z);
G(&v1, &v5, &v9, &vD, Z, Z);
G(&v2, &v6, &vA, &vE, m0, Z);
G(&v3, &v7, &vB, &vF, Z, m3);
- /**
- * r=5, i=4, a=v[0], b=v[5], c=v[10], d=v[15], m[sigma]=4, m[sigma+1]=13
- * r=5, i=5, a=v[1], b=v[6], c=v[11], d=v[12], m[sigma]=7, m[sigma+1]=5
- * r=5, i=6, a=v[2], b=v[7], c=v[8], d=v[13], m[sigma]=15, m[sigma+1]=14
- * r=5, i=7, a=v[3], b=v[4], c=v[9], d=v[14], m[sigma]=1, m[sigma+1]=9
- */
G(&v0, &v5, &vA, &vF, m4, Z);
G(&v1, &v6, &vB, &vC, Z, Z);
G(&v2, &v7, &v8, &vD, Z, Z);
G(&v3, &v4, &v9, &vE, m1, Z);
- /****************************************************************************
- * ROUND(6) *
- ****************************************************************************/
-
/**
- * r=6, i=0, a=v[0], b=v[4], c=v[8], d=v[12], m[sigma]=12, m[sigma+1]=5
- * r=6, i=1, a=v[1], b=v[5], c=v[9], d=v[13], m[sigma]=1, m[sigma+1]=15
- * r=6, i=2, a=v[2], b=v[6], c=v[10], d=v[14], m[sigma]=14, m[sigma+1]=13
- * r=6, i=3, a=v[3], b=v[7], c=v[11], d=v[15], m[sigma]=4, m[sigma+1]=10
+ * ROUND(6)
+ * m[sigma]=(12,5),(1,15),(14,13),(4,10)
+ * m[sigma]=(0,7),(6,3),(9,2),(8,11)
*/
G(&v0, &v4, &v8, &vC, Z, Z);
G(&v1, &v5, &v9, &vD, m1, Z);
G(&v2, &v6, &vA, &vE, Z, Z);
G(&v3, &v7, &vB, &vF, m4, Z);
- /**
- * r=6, i=4, a=v[0], b=v[5], c=v[10], d=v[15], m[sigma]=0, m[sigma+1]=7
- * r=6, i=5, a=v[1], b=v[6], c=v[11], d=v[12], m[sigma]=6, m[sigma+1]=3
- * r=6, i=6, a=v[2], b=v[7], c=v[8], d=v[13], m[sigma]=9, m[sigma+1]=2
- * r=6, i=7, a=v[3], b=v[4], c=v[9], d=v[14], m[sigma]=8, m[sigma+1]=11
- */
G(&v0, &v5, &vA, &vF, m0, Z);
G(&v1, &v6, &vB, &vC, Z, m3);
G(&v2, &v7, &v8, &vD, Z, m2);
G(&v3, &v4, &v9, &vE, Z, Z);
- /****************************************************************************
- * ROUND(7) *
- ****************************************************************************/
-
/**
- * r=7, i=0, a=v[0], b=v[4], c=v[8], d=v[12], m[sigma]=13, m[sigma+1]=11
- * r=7, i=1, a=v[1], b=v[5], c=v[9], d=v[13], m[sigma]=7, m[sigma+1]=14
- * r=7, i=2, a=v[2], b=v[6], c=v[10], d=v[14], m[sigma]=12, m[sigma+1]=1
- * r=7, i=3, a=v[3], b=v[7], c=v[11], d=v[15], m[sigma]=3, m[sigma+1]=9
+ * ROUND(7)
+ * m[sigma]=(13,11),(7,14),(12,1),(3,9)
+ * m[sigma]=(5,0),(15,4),(8,6),(2,10)
*/
G(&v0, &v4, &v8, &vC, Z, Z);
G(&v1, &v5, &v9, &vD, Z, Z);
G(&v2, &v6, &vA, &vE, Z, m1);
G(&v3, &v7, &vB, &vF, m3, Z);
- /**
- * r=7, i=4, a=v[0], b=v[5], c=v[10], d=v[15], m[sigma]=5, m[sigma+1]=0
- * r=7, i=5, a=v[1], b=v[6], c=v[11], d=v[12], m[sigma]=15, m[sigma+1]=4
- * r=7, i=6, a=v[2], b=v[7], c=v[8], d=v[13], m[sigma]=8, m[sigma+1]=6
- * r=7, i=7, a=v[3], b=v[4], c=v[9], d=v[14], m[sigma]=2, m[sigma+1]=10
- */
G(&v0, &v5, &vA, &vF, Z, m0);
G(&v1, &v6, &vB, &vC, Z, m4);
G(&v2, &v7, &v8, &vD, Z, Z);
G(&v3, &v4, &v9, &vE, m2, Z);
- /****************************************************************************
- * ROUND(8) *
- ****************************************************************************/
-
/**
- * r=8, i=0, a=v[0], b=v[4], c=v[8], d=v[12], m[sigma]=6, m[sigma+1]=15
- * r=8, i=1, a=v[1], b=v[5], c=v[9], d=v[13], m[sigma]=14, m[sigma+1]=9
- * r=8, i=2, a=v[2], b=v[6], c=v[10], d=v[14], m[sigma]=11, m[sigma+1]=3
- * r=8, i=3, a=v[3], b=v[7], c=v[11], d=v[15], m[sigma]=0, m[sigma+1]=8
+ * ROUND(8)
+ * m[sigma]=(6,15),(14,9),(11,3),(0,8)
+ * m[sigma]=(12,2),(13,7),(1,4),(10,5)
*/
G(&v0, &v4, &v8, &vC, Z, Z);
G(&v1, &v5, &v9, &vD, Z, Z);
G(&v2, &v6, &vA, &vE, Z, m3);
G(&v3, &v7, &vB, &vF, m0, Z);
- /**
- * r=8, i=4, a=v[0], b=v[5], c=v[10], d=v[15], m[sigma]=12, m[sigma+1]=2
- * r=8, i=5, a=v[1], b=v[6], c=v[11], d=v[12], m[sigma]=13, m[sigma+1]=7
- * r=8, i=6, a=v[2], b=v[7], c=v[8], d=v[13], m[sigma]=1, m[sigma+1]=4
- * r=8, i=7, a=v[3], b=v[4], c=v[9], d=v[14], m[sigma]=10, m[sigma+1]=5
- */
G(&v0, &v5, &vA, &vF, Z, m2);
G(&v1, &v6, &vB, &vC, Z, Z);
G(&v2, &v7, &v8, &vD, m1, m4);
G(&v3, &v4, &v9, &vE, Z, Z);
- /****************************************************************************
- * ROUND(9) *
- ****************************************************************************/
-
/**
- * r=9, i=0, a=v[0], b=v[4], c=v[8], d=v[12], m[sigma]=10, m[sigma+1]=2
- * r=9, i=1, a=v[1], b=v[5], c=v[9], d=v[13], m[sigma]=8, m[sigma+1]=4
- * r=9, i=2, a=v[2], b=v[6], c=v[10], d=v[14], m[sigma]=7, m[sigma+1]=6
- * r=9, i=3, a=v[3], b=v[7], c=v[11], d=v[15], m[sigma]=1, m[sigma+1]=5
+ * ROUND(9)
+ * m[sigma]=(10,2),(8,4),(7,6),(1,5)
+ * m[sigma]=(15,11),(9,14),(3,12),(13,0)
*/
G(&v0, &v4, &v8, &vC, Z, m2);
G(&v1, &v5, &v9, &vD, Z, m4);
G(&v2, &v6, &vA, &vE, Z, Z);
G(&v3, &v7, &vB, &vF, m1, Z);
- /**
- * r=9, i=4, a=v[0], b=v[5], c=v[10], d=v[15], m[sigma]=15, m[sigma+1]=11
- * r=9, i=5, a=v[1], b=v[6], c=v[11], d=v[12], m[sigma]=9, m[sigma+1]=14
- * r=9, i=6, a=v[2], b=v[7], c=v[8], d=v[13], m[sigma]=3, m[sigma+1]=12
- * r=9, i=7, a=v[3], b=v[4], c=v[9], d=v[14], m[sigma]=13, m[sigma+1]=0
- */
G(&v0, &v5, &vA, &vF, Z, Z);
G(&v1, &v6, &vB, &vC, Z, Z);
G(&v2, &v7, &v8, &vD, m3, Z);
G(&v3, &v4, &v9, &vE, Z, m0);
- /****************************************************************************
- * ROUND(10) *
- ****************************************************************************/
-
/**
- * r=10, i=0, a=v[0], b=v[4], c=v[8], d=v[12], m[sigma]=0, m[sigma+1]=1
- * r=10, i=1, a=v[1], b=v[5], c=v[9], d=v[13], m[sigma]=2, m[sigma+1]=3
- * r=10, i=2, a=v[2], b=v[6], c=v[10], d=v[14], m[sigma]=4, m[sigma+1]=5
- * r=10, i=3, a=v[3], b=v[7], c=v[11], d=v[15], m[sigma]=6, m[sigma+1]=7
+ * ROUND(10)
+ * m[sigma]=(0,1),(2,3),(4,5),(6,7)
+ * m[sigma]=(8,9),(10,11),(12,13),(14,15)
*/
G(&v0, &v4, &v8, &vC, m0, m1);
G(&v1, &v5, &v9, &vD, m2, m3);
G(&v2, &v6, &vA, &vE, m4, Z);
G(&v3, &v7, &vB, &vF, Z, Z);
- /**
- * r=10, i=4, a=v[0], b=v[5], c=v[10], d=v[15], m[sigma]=8, m[sigma+1]=9
- * r=10, i=5, a=v[1], b=v[6], c=v[11], d=v[12], m[sigma]=10, m[sigma+1]=11
- * r=10, i=6, a=v[2], b=v[7], c=v[8], d=v[13], m[sigma]=12, m[sigma+1]=13
- * r=10, i=7, a=v[3], b=v[4], c=v[9], d=v[14], m[sigma]=14, m[sigma+1]=15
- */
G(&v0, &v5, &vA, &vF, Z, Z);
G(&v1, &v6, &vB, &vC, Z, Z);
G(&v2, &v7, &v8, &vD, Z, Z);
G(&v3, &v4, &v9, &vE, Z, Z);
- /****************************************************************************
- * ROUND(11) *
- ****************************************************************************/
-
/**
- * r=11, i=0, a=v[0], b=v[4], c=v[8], d=v[12], m[sigma]=14, m[sigma+1]=10
- * r=11, i=1, a=v[1], b=v[5], c=v[9], d=v[13], m[sigma]=4, m[sigma+1]=8
- * r=11, i=2, a=v[2], b=v[6], c=v[10], d=v[14], m[sigma]=9, m[sigma+1]=15
- * r=11, i=3, a=v[3], b=v[7], c=v[11], d=v[15], m[sigma]=13, m[sigma+1]=6
+ * ROUND(11)
+ * m[sigma]=(14,10),(4,8),(9,15),(13,6)
+ * m[sigma]=(1,12),(0,2),(11,7),(5,3)
*/
G(&v0, &v4, &v8, &vC, Z, Z);
G(&v1, &v5, &v9, &vD, m4, Z);
G(&v2, &v6, &vA, &vE, Z, Z);
G(&v3, &v7, &vB, &vF, Z, Z);
- /**
- * r=11, i=4, a=v[0], b=v[5], c=v[10], d=v[15], m[sigma]=1, m[sigma+1]=12
- * r=11, i=5, a=v[1], b=v[6], c=v[11], d=v[12], m[sigma]=0, m[sigma+1]=2
- * r=11, i=6, a=v[2], b=v[7], c=v[8], d=v[13], m[sigma]=11, m[sigma+1]=7
- * r=11, i=7, a=v[3], b=v[4], c=v[9], d=v[14], m[sigma]=5, m[sigma+1]=3
- */
G(&v0, &v5, &vA, &vF, m1, Z);
// G(&v1, &v6, &vB, &vC, m0, m2);
G(&v2, &v7, &v8, &vD, Z, Z);
* Set nonce if it passes the difficulty threshold and no other thread has set it.
*/
var result: vec2<u32> = BLAKE2B_INIT[0u] ^ v0 ^ v8;
- if (validate || ((result.y > ubo.difficulty.y || (result.y == ubo.difficulty.y && result.y >= ubo.difficulty.y)) && atomicLoad(&work.found) == 0u)) {
+ if (validate || ((result.y > ubo.difficulty.y || (result.y == ubo.difficulty.y && result.x >= ubo.difficulty.x)) && atomicLoad(&work.found) == 0u)) {
atomicStore(&work.found, 1u);
work.nonce = m0;
work.result = result;