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
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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
+7 −2
Original line number Diff line number Diff line
@@ -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,
+7 −4
Original line number Diff line number Diff line
@@ -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 {
+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', () => {
@@ -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)
  })

});