Commit 7ac480f7 authored by Cédric Moreau's avatar Cédric Moreau
Browse files

[fix] #1234 PoW workers were not cancelling their current proof when asked

parent 49537b7c
......@@ -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
......
......@@ -15,6 +15,8 @@ let clusterId = 0
*/
export class Master {
nbCancels = 0
clusterId:number
currentPromise:any|null = null
slaves:any[] = []
......@@ -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)
}
......@@ -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'
......@@ -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,
......
......@@ -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;
......@@ -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) {
......@@ -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
}
}
......@@ -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
......@@ -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)
}
}
......@@ -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
}
/*****************
......@@ -236,6 +238,7 @@ function beginNewProofOfWork(stuff:any) {
// PoW stopped
askedStop = false;
pSend({ canceled: true })
return null
} else {
......
"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', () => {
......@@ -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)
})
});
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment