import { Blake2b } from "@iota/crypto.js" ; import { IPowProvider , PowHelper } from "@iota/iota.js" ; import os from "os" ; import path from "path" ; import { Worker } from "worker_threads" ; /**
 * Node POW Provider.
 */ export class NodePowProvider implements IPowProvider { internal private readonly _numCpus : number ; param numCpus constructor ( numCpus ? ) { this . _numCpus = numCpus ?? os . cpus ( ) . length ; } param message param targetScore returns public async pow ( message , targetScore ) { const powRelevantData = message . slice ( 0 , - 8 ) ; const powDigest = Blake2b . sum256 ( powRelevantData ) ; const targetZeros = PowHelper . calculateTargetZeros ( message , targetScore ) ; return new Promise < string > ( ( resolve , reject ) => { const chunkSize = BigInt ( "18446744073709551615" ) / BigInt ( this . _numCpus ) ; const workers = [ ] ; let hasFinished = false ; for ( let i = 0 ; i < this . _numCpus ; i ++ ) { const worker = new Worker ( path . join ( __dirname , "pow-node.js" ) , { workerData : { powDigest , targetZeros , startIndex : ( chunkSize * BigInt ( i ) ) . toString ( ) } } ) ; workers . push ( worker ) ; worker . on ( "message" , async ( msg ) => { hasFinished = true ; for ( let j = 0 ; j < workers . length ; j ++ ) { await workers [ j ] . terminate ( ) ; } resolve ( msg ) ; } ) ; worker . on ( "error" , err => { reject ( err ) ; } ) ; worker . on ( "exit" , code => { if ( ! hasFinished && code !== 0 ) { reject ( new Error ( `Worker stopped with exit code ${ code }` ) ) ; } } ) ; } } ) ; } }