Loading app/modules/prover/lib/constants.ts +1 −0 Original line number Diff line number Diff line Loading @@ -13,6 +13,7 @@ export const ProverConstants = { NONCE_RANGE: 1000 * 1000 * 1000 * 100, POW_MAXIMUM_ACCEPTABLE_HANDICAP: 64, POW_NB_PAUSES_PER_ROUND: 10, // When to trigger the PoW process again if no PoW is triggered for a while. In milliseconds. POW_SECURITY_RETRY_DELAY: 10 * 60 * 1000 Loading app/modules/prover/lib/powCluster.ts +7 −2 Original line number Diff line number Diff line Loading @@ -15,6 +15,8 @@ let clusterId = 0 */ export class Master { nbCancels = 0 clusterId:number currentPromise:any|null = null slaves:any[] = [] Loading Loading @@ -54,6 +56,8 @@ export class Master { this.currentPromise.extras.resolve(message.answer) // Stop the slaves' current work this.cancelWork() } else if (message.canceled) { this.nbCancels++ } // this.logger.debug(`ENGINE c#${this.clusterId}#${this.slavesMap[worker.id].index}:`, message) } Loading Loading @@ -130,7 +134,7 @@ export class Master { } cancelWork() { this.logger.info(`Cancelling the work on PoW cluster`) this.logger.info(`Cancelling the work on PoW cluster of %s slaves`, this.slaves.length) this.slaves.forEach(s => { s.worker.send({ command: 'cancel' Loading Loading @@ -189,7 +193,8 @@ export class Master { uuid, command: 'newPoW', value: { block: stuff.newPoW.block, initialTestsPerRound: stuff.initialTestsPerRound, maxDuration: stuff.maxDuration,block: stuff.newPoW.block, nonceBeginning: s.nonceBeginning, zeros: stuff.newPoW.zeros, highMark: stuff.newPoW.highMark, Loading app/modules/prover/lib/proof.ts +7 −4 Original line number Diff line number Diff line Loading @@ -74,6 +74,7 @@ function beginNewProofOfWork(stuff:any) { ****************/ let nonce = 0; const maxDuration = stuff.maxDuration || 1000 const conf = stuff.conf; const block = stuff.block; const nonceBeginning = stuff.nonceBeginning; Loading Loading @@ -101,13 +102,14 @@ function beginNewProofOfWork(stuff:any) { * GO! ****************/ let pausePeriod = 1; let testsCount = 0; let found = false; let turn = 0; const profiler = new ProcessCpuProfiler(100) let cpuUsage = profiler.cpuUsageOverLastMilliseconds(1) // We limit the number of tests according to CPU usage let testsPerRound = 1 let testsPerRound = stuff.initialTestsPerRound || 1 let turnDuration = 20 // We initially goes quickly to the max speed = 50 reevaluations per second (1000 / 20) while (!found && !askedStop) { Loading Loading @@ -178,7 +180,7 @@ function beginNewProofOfWork(stuff:any) { if (!found && !askedStop) { i++; testsCount++; if (i % testsPerRound === 0) { if (i % pausePeriod === 0) { await countDown(0); // Very low pause, just the time to process eventual end of the turn } } Loading @@ -191,7 +193,6 @@ function beginNewProofOfWork(stuff:any) { // CPU speed recording if (turn > 0) { const oldTestsPerRound = testsPerRound cpuUsage = profiler.cpuUsageOverLastMilliseconds(turnDuration) if (cpuUsage > currentCPU + 0.005 || cpuUsage < currentCPU - 0.005) { let powVariationFactor Loading @@ -203,6 +204,7 @@ function beginNewProofOfWork(stuff:any) { powVariationFactor = 0.99 testsPerRound = Math.max(1, Math.floor(testsPerRound * powVariationFactor)) } pausePeriod = Math.floor(testsPerRound / ProverConstants.POW_NB_PAUSES_PER_ROUND) } } Loading @@ -222,7 +224,7 @@ function beginNewProofOfWork(stuff:any) { turn++ turnDuration += 1 turnDuration = Math.min(turnDuration, 1000) // Max 1 second per turn turnDuration = Math.min(turnDuration, maxDuration) // Max 1 second per turn } /***************** Loading @@ -236,6 +238,7 @@ function beginNewProofOfWork(stuff:any) { // PoW stopped askedStop = false; pSend({ canceled: true }) return null } else { Loading test/fast/prover/pow-1-cluster.js→test/fast/prover/pow-1-cluster.ts +35 −5 Original line number Diff line number Diff line "use strict"; import {Master} from "../../../app/modules/prover/lib/powCluster" const co = require('co') const should = require('should') const PowCluster = require('../../../app/modules/prover/lib/powCluster').Master require('should') const logger = require('../../../app/lib/logger').NewLogger() let master let master:Master describe('PoW Cluster', () => { before(() => { master = new PowCluster(1, logger) master = new Master(1, logger) }) it('should have an empty cluster if no PoW was asked', () => { Loading Loading @@ -73,4 +72,35 @@ describe('PoW Cluster', () => { delay.should.be.below(50) })) it('should be able to stop all the cores on cancel', async () => { master.proveByWorkers({ initialTestsPerRound: 100, maxDuration: 1000, newPoW: { block: { number: 0 }, zeros: 10, highMark: 'F', conf: { medianTimeBlocks: 1, avgGenTime: 100, cpu: 0.8, prefix: '8', nbCores: 1 }, pair: { pub: 'HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd', sec: '51w4fEShBk1jCMauWu4mLpmDVfHksKmWcygpxriqCEZizbtERA6de4STKRkQBpxmMUwsKXRjSzuQ8ECwmqN1u2DP' } } }) await new Promise(res => { master.onInfoMessage = () => res() }) await master.cancelWork() await new Promise(res => setTimeout(res, 100)) master.nbCancels.should.equal(1) }) }); Loading
app/modules/prover/lib/constants.ts +1 −0 Original line number Diff line number Diff line Loading @@ -13,6 +13,7 @@ export const ProverConstants = { NONCE_RANGE: 1000 * 1000 * 1000 * 100, POW_MAXIMUM_ACCEPTABLE_HANDICAP: 64, POW_NB_PAUSES_PER_ROUND: 10, // When to trigger the PoW process again if no PoW is triggered for a while. In milliseconds. POW_SECURITY_RETRY_DELAY: 10 * 60 * 1000 Loading
app/modules/prover/lib/powCluster.ts +7 −2 Original line number Diff line number Diff line Loading @@ -15,6 +15,8 @@ let clusterId = 0 */ export class Master { nbCancels = 0 clusterId:number currentPromise:any|null = null slaves:any[] = [] Loading Loading @@ -54,6 +56,8 @@ export class Master { this.currentPromise.extras.resolve(message.answer) // Stop the slaves' current work this.cancelWork() } else if (message.canceled) { this.nbCancels++ } // this.logger.debug(`ENGINE c#${this.clusterId}#${this.slavesMap[worker.id].index}:`, message) } Loading Loading @@ -130,7 +134,7 @@ export class Master { } cancelWork() { this.logger.info(`Cancelling the work on PoW cluster`) this.logger.info(`Cancelling the work on PoW cluster of %s slaves`, this.slaves.length) this.slaves.forEach(s => { s.worker.send({ command: 'cancel' Loading Loading @@ -189,7 +193,8 @@ export class Master { uuid, command: 'newPoW', value: { block: stuff.newPoW.block, initialTestsPerRound: stuff.initialTestsPerRound, maxDuration: stuff.maxDuration,block: stuff.newPoW.block, nonceBeginning: s.nonceBeginning, zeros: stuff.newPoW.zeros, highMark: stuff.newPoW.highMark, Loading
app/modules/prover/lib/proof.ts +7 −4 Original line number Diff line number Diff line Loading @@ -74,6 +74,7 @@ function beginNewProofOfWork(stuff:any) { ****************/ let nonce = 0; const maxDuration = stuff.maxDuration || 1000 const conf = stuff.conf; const block = stuff.block; const nonceBeginning = stuff.nonceBeginning; Loading Loading @@ -101,13 +102,14 @@ function beginNewProofOfWork(stuff:any) { * GO! ****************/ let pausePeriod = 1; let testsCount = 0; let found = false; let turn = 0; const profiler = new ProcessCpuProfiler(100) let cpuUsage = profiler.cpuUsageOverLastMilliseconds(1) // We limit the number of tests according to CPU usage let testsPerRound = 1 let testsPerRound = stuff.initialTestsPerRound || 1 let turnDuration = 20 // We initially goes quickly to the max speed = 50 reevaluations per second (1000 / 20) while (!found && !askedStop) { Loading Loading @@ -178,7 +180,7 @@ function beginNewProofOfWork(stuff:any) { if (!found && !askedStop) { i++; testsCount++; if (i % testsPerRound === 0) { if (i % pausePeriod === 0) { await countDown(0); // Very low pause, just the time to process eventual end of the turn } } Loading @@ -191,7 +193,6 @@ function beginNewProofOfWork(stuff:any) { // CPU speed recording if (turn > 0) { const oldTestsPerRound = testsPerRound cpuUsage = profiler.cpuUsageOverLastMilliseconds(turnDuration) if (cpuUsage > currentCPU + 0.005 || cpuUsage < currentCPU - 0.005) { let powVariationFactor Loading @@ -203,6 +204,7 @@ function beginNewProofOfWork(stuff:any) { powVariationFactor = 0.99 testsPerRound = Math.max(1, Math.floor(testsPerRound * powVariationFactor)) } pausePeriod = Math.floor(testsPerRound / ProverConstants.POW_NB_PAUSES_PER_ROUND) } } Loading @@ -222,7 +224,7 @@ function beginNewProofOfWork(stuff:any) { turn++ turnDuration += 1 turnDuration = Math.min(turnDuration, 1000) // Max 1 second per turn turnDuration = Math.min(turnDuration, maxDuration) // Max 1 second per turn } /***************** Loading @@ -236,6 +238,7 @@ function beginNewProofOfWork(stuff:any) { // PoW stopped askedStop = false; pSend({ canceled: true }) return null } else { Loading
test/fast/prover/pow-1-cluster.js→test/fast/prover/pow-1-cluster.ts +35 −5 Original line number Diff line number Diff line "use strict"; import {Master} from "../../../app/modules/prover/lib/powCluster" const co = require('co') const should = require('should') const PowCluster = require('../../../app/modules/prover/lib/powCluster').Master require('should') const logger = require('../../../app/lib/logger').NewLogger() let master let master:Master describe('PoW Cluster', () => { before(() => { master = new PowCluster(1, logger) master = new Master(1, logger) }) it('should have an empty cluster if no PoW was asked', () => { Loading Loading @@ -73,4 +72,35 @@ describe('PoW Cluster', () => { delay.should.be.below(50) })) it('should be able to stop all the cores on cancel', async () => { master.proveByWorkers({ initialTestsPerRound: 100, maxDuration: 1000, newPoW: { block: { number: 0 }, zeros: 10, highMark: 'F', conf: { medianTimeBlocks: 1, avgGenTime: 100, cpu: 0.8, prefix: '8', nbCores: 1 }, pair: { pub: 'HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd', sec: '51w4fEShBk1jCMauWu4mLpmDVfHksKmWcygpxriqCEZizbtERA6de4STKRkQBpxmMUwsKXRjSzuQ8ECwmqN1u2DP' } } }) await new Promise(res => { master.onInfoMessage = () => res() }) await master.cancelWork() await new Promise(res => setTimeout(res, 100)) master.nbCancels.should.equal(1) }) });