From 56fe94f903afba1d309ec2b9baddf03d4bfe50ab Mon Sep 17 00:00:00 2001
From: Vincent Rousseau <vincent.rousseau@irstea.fr>
Date: Sat, 2 Dec 2017 20:31:31 +0100
Subject: [PATCH 1/7] Add eco mode

---
 app/cli.ts                            |  1 +
 app/lib/dto/ConfDTO.ts                |  3 ++-
 app/modules/prover/lib/blockProver.ts | 19 +++++++++++---
 app/modules/prover/lib/powCluster.ts  | 38 ++++++++++++++-------------
 index.ts                              |  2 ++
 test/integration/proof-of-work.js     | 16 +++++++++--
 6 files changed, 55 insertions(+), 24 deletions(-)

diff --git a/app/cli.ts b/app/cli.ts
index 3c2e49515..6a6d3924b 100644
--- a/app/cli.ts
+++ b/app/cli.ts
@@ -41,6 +41,7 @@ export const ExecuteCommand = () => {
         .option('--addep <endpoint>', 'With `config` command, add given endpoint to the list of endpoints of this node')
         .option('--remep <endpoint>', 'With `config` command, remove given endpoint to the list of endpoints of this node')
 
+        .option('--no-eco-mode', 'Do not reduce CPU usage for proof-of-work computation')
         .option('--cpu <percent>', 'Percent of CPU usage for proof-of-work computation', parsePercent)
         .option('--nb-cores <number>', 'Number of cores uses for proof-of-work computation', parseInt)
         .option('--prefix <nodeId>', 'Prefix node id for the first character of nonce', parseInt)
diff --git a/app/lib/dto/ConfDTO.ts b/app/lib/dto/ConfDTO.ts
index 2e77e92fc..b6ff36a94 100644
--- a/app/lib/dto/ConfDTO.ts
+++ b/app/lib/dto/ConfDTO.ts
@@ -91,6 +91,7 @@ export class ConfDTO implements CurrencyConfDTO, KeypairConfDTO, NetworkConfDTO,
     public rmEndpoints: string[],
     public rootoffset: number,
     public upInterval: number,
+    public ecoMode: boolean|true,
     public cpu: number,
     public nbCores: number,
     public prefix: number,
@@ -162,7 +163,7 @@ export class ConfDTO implements CurrencyConfDTO, KeypairConfDTO, NetworkConfDTO,
 ) {}
 
   static mock() {
-    return new ConfDTO("", "", [], [], 0, 3600 * 1000, constants.PROOF_OF_WORK.DEFAULT.CPU, 1, constants.PROOF_OF_WORK.DEFAULT.PREFIX, 0, 0, constants.CONTRACT.DEFAULT.C, constants.CONTRACT.DEFAULT.DT, constants.CONTRACT.DEFAULT.DT_REEVAL, 0, constants.CONTRACT.DEFAULT.UD0, 0, 0, constants.CONTRACT.DEFAULT.STEPMAX, constants.CONTRACT.DEFAULT.SIGPERIOD, 0, constants.CONTRACT.DEFAULT.SIGVALIDITY, constants.CONTRACT.DEFAULT.MSVALIDITY, constants.CONTRACT.DEFAULT.SIGQTY, constants.CONTRACT.DEFAULT.SIGSTOCK, constants.CONTRACT.DEFAULT.X_PERCENT, constants.CONTRACT.DEFAULT.PERCENTROT, constants.CONTRACT.DEFAULT.POWDELAY, constants.CONTRACT.DEFAULT.AVGGENTIME, constants.CONTRACT.DEFAULT.MEDIANTIMEBLOCKS, false, 3000, false, constants.BRANCHES.DEFAULT_WINDOW_SIZE, constants.CONTRACT.DEFAULT.IDTYWINDOW, constants.CONTRACT.DEFAULT.MSWINDOW, constants.CONTRACT.DEFAULT.SIGWINDOW, 0, { pub:'', sec:'' }, null, "", "", 0, "", "", "", "", 0, "", "", null, false, "", true, true, false, new ProxiesConf(), undefined)
+    return new ConfDTO("", "", [], [], 0, 3600 * 1000, true, constants.PROOF_OF_WORK.DEFAULT.CPU, 1, constants.PROOF_OF_WORK.DEFAULT.PREFIX, 0, 0, constants.CONTRACT.DEFAULT.C, constants.CONTRACT.DEFAULT.DT, constants.CONTRACT.DEFAULT.DT_REEVAL, 0, constants.CONTRACT.DEFAULT.UD0, 0, 0, constants.CONTRACT.DEFAULT.STEPMAX, constants.CONTRACT.DEFAULT.SIGPERIOD, 0, constants.CONTRACT.DEFAULT.SIGVALIDITY, constants.CONTRACT.DEFAULT.MSVALIDITY, constants.CONTRACT.DEFAULT.SIGQTY, constants.CONTRACT.DEFAULT.SIGSTOCK, constants.CONTRACT.DEFAULT.X_PERCENT, constants.CONTRACT.DEFAULT.PERCENTROT, constants.CONTRACT.DEFAULT.POWDELAY, constants.CONTRACT.DEFAULT.AVGGENTIME, constants.CONTRACT.DEFAULT.MEDIANTIMEBLOCKS, false, 3000, false, constants.BRANCHES.DEFAULT_WINDOW_SIZE, constants.CONTRACT.DEFAULT.IDTYWINDOW, constants.CONTRACT.DEFAULT.MSWINDOW, constants.CONTRACT.DEFAULT.SIGWINDOW, 0, { pub:'', sec:'' }, null, "", "", 0, "", "", "", "", 0, "", "", null, false, "", true, true, false, new ProxiesConf(), undefined)
   }
 
   static defaultConf() {
diff --git a/app/modules/prover/lib/blockProver.ts b/app/modules/prover/lib/blockProver.ts
index 9cd215d98..1b6d051c2 100644
--- a/app/modules/prover/lib/blockProver.ts
+++ b/app/modules/prover/lib/blockProver.ts
@@ -177,6 +177,7 @@ export class BlockProver {
         newPoW: {
           turnDuration: os.arch().match(/arm/) ? CommonConstants.POW_TURN_DURATION_ARM : CommonConstants.POW_TURN_DURATION_PC,
           conf: {
+            nbCores: this.conf.nbCores,
             cpu: this.conf.cpu,
             prefix: this.conf.prefix,
             avgGenTime: this.conf.avgGenTime,
@@ -196,16 +197,28 @@ export class BlockProver {
         const proof = result.block;
         const testsCount = result.testsCount;
         const duration = (Date.now() - start);
-        const testsPerSecond = (testsCount / (duration / 1000)).toFixed(2);
-        this.logger.info('Done: #%s, %s in %ss (%s tests, ~%s tests/s)', block.number, proof.hash, (duration / 1000).toFixed(2), testsCount, testsPerSecond);
+        const testsPerSecond = (testsCount / (duration / 1000));
+        this.logger.info('Done: #%s, %s in %ss instead of %ss (%s tests, ~%s tests/s)', block.number, proof.hash, (duration / 1000).toFixed(2),
+                                                                        this.conf.avgGenTime, testsCount, testsPerSecond.toFixed(2));
         this.logger.info('FOUND proof-of-work with %s leading zeros followed by [0-' + highMark + ']!', nbZeros);
+        if(this.conf.ecoMode && this.conf.nbCores*testsPerSecond > 300) {
+          if(this.conf.nbCores > 1) {
+            this.logger.info("Reducing number of CPU cores "+this.conf.nbCores)
+            this.conf.nbCores = this.conf.nbCores -1
+          }
+          else if(this.conf.cpu > 0.19){
+            let cpu:number = this.conf.cpu - 0.1
+            this.logger.info("Slowing down the CPU to "+cpu)
+            this.changeCPU(cpu)
+          }
+        }
         return BlockDTO.fromJSONObject(proof)
       }
     })()
   };
 
   async changeCPU(cpu:number) {
-    this.conf.cpu = cpu;
+    this.conf.cpu = Math.max(0.01, Math.min(1.0, cpu));
     const farm = await this.getWorker()
     return farm.changeCPU(cpu)
   }
diff --git a/app/modules/prover/lib/powCluster.ts b/app/modules/prover/lib/powCluster.ts
index 4d4820777..8e6e65843 100644
--- a/app/modules/prover/lib/powCluster.ts
+++ b/app/modules/prover/lib/powCluster.ts
@@ -185,25 +185,27 @@ export class Master {
 
       // Start the salves' job
       this.slaves.forEach((s:any, index) => {
-        s.worker.send({
-          uuid,
-          command: 'newPoW',
-          value: {
-            block: stuff.newPoW.block,
-            nonceBeginning: s.nonceBeginning,
-            zeros: stuff.newPoW.zeros,
-            highMark: stuff.newPoW.highMark,
-            pair: _.clone(stuff.newPoW.pair),
-            forcedTime: stuff.newPoW.forcedTime,
-            turnDuration: stuff.newPoW.turnDuration,
-            conf: {
-              medianTimeBlocks: stuff.newPoW.conf.medianTimeBlocks,
-              avgGenTime: stuff.newPoW.conf.avgGenTime,
-              cpu: stuff.newPoW.conf.cpu,
-              prefix: stuff.newPoW.conf.prefix
+        if(index < stuff.newPoW.conf.nbCores) {
+          s.worker.send({
+            uuid,
+            command: 'newPoW',
+            value: {
+              block: stuff.newPoW.block,
+              nonceBeginning: s.nonceBeginning,
+              zeros: stuff.newPoW.zeros,
+              highMark: stuff.newPoW.highMark,
+              pair: _.clone(stuff.newPoW.pair),
+              forcedTime: stuff.newPoW.forcedTime,
+              turnDuration: stuff.newPoW.turnDuration,
+              conf: {
+                medianTimeBlocks: stuff.newPoW.conf.medianTimeBlocks,
+                avgGenTime: stuff.newPoW.conf.avgGenTime,
+                cpu: stuff.newPoW.conf.cpu,
+                prefix: stuff.newPoW.conf.prefix
+              }
             }
-          }
-        })
+          })
+        }
       })
 
       return await this.currentPromise
diff --git a/index.ts b/index.ts
index ecf7be9d6..daf1b333b 100644
--- a/index.ts
+++ b/index.ts
@@ -443,6 +443,7 @@ function commandLineConf(program:any, conf:any = {}) {
   conf = conf || {};
   const cli = {
     currency: program.currency,
+    ecoMode: program.ecoMode,
     cpu: program.cpu,
     nbCores: program.nbCores,
     prefix: program.prefix,
@@ -485,6 +486,7 @@ function commandLineConf(program:any, conf:any = {}) {
   // Update the rest of the conf
   if (cli.currency)                             conf.currency = cli.currency;
   if (cli.server.port)                          conf.port = cli.server.port;
+  if (cli.ecoMode)                              conf.ecoMode = cli.ecoMode
   if (cli.cpu)                                  conf.cpu = Math.max(0.01, Math.min(1.0, cli.cpu));
   if (cli.prefix)                               conf.prefix = Math.max(ProverConstants.MIN_PEER_ID, Math.min(ProverConstants.MAX_PEER_ID, cli.prefix));
   if (cli.logs.http)                            conf.httplogs = true;
diff --git a/test/integration/proof-of-work.js b/test/integration/proof-of-work.js
index f2540c606..dd507167a 100644
--- a/test/integration/proof-of-work.js
+++ b/test/integration/proof-of-work.js
@@ -16,13 +16,15 @@ keyring from Key
 ***/
 
 const intermediateProofs = [];
-const NB_CORES_FOR_COMPUTATION = 1 // For simple tests. Can be changed to test multiple cores.
+const NB_CORES_FOR_COMPUTATION = 2 // For simple tests. Can be changed to test multiple cores.
 
 const prover = new BlockProver({
   push: (data) => intermediateProofs.push(data),
   conf: {
+    avgGenTime: 20,//1*60,
+    ecoMode: true,
     nbCores: NB_CORES_FOR_COMPUTATION,
-    cpu: 1.0, // 80%,
+    cpu: 0.8, // 80%,
     pair: {
       pub: 'HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd',
       sec: '51w4fEShBk1jCMauWu4mLpmDVfHksKmWcygpxriqCEZizbtERA6de4STKRkQBpxmMUwsKXRjSzuQ8ECwmqN1u2DP'
@@ -34,9 +36,11 @@ const prover = new BlockProver({
 const now = 1474382274 * 1000;
 const MUST_START_WITH_A_ZERO = 16;
 const MUST_START_WITH_TWO_ZEROS = 32;
+const MUST_START_WITH_THREE_ZEROS = 58;
 
 describe("Proof-of-work", function() {
 
+  this.timeout(6*60000)
   it('should be able to find an easy PoW', () => co(function*() {
     let block = yield prover.prove({
       issuer: 'HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd',
@@ -48,6 +52,14 @@ describe("Proof-of-work", function() {
     intermediateProofs[intermediateProofs.length - 1].pow.should.have.property('hash').equal(block.hash);
   }));
 
+  it('should be reducing cpu when the PoW is too easy for the cpu', () => co(function*() {
+    for(let i=0; i<8; ++i) {
+      let block = yield prover.prove({
+        issuer: 'HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd',
+        number: i+2
+      }, MUST_START_WITH_THREE_ZEROS, now);
+    }
+  }));
   // Too randomly successing test
   // it('should be able to cancel a proof-of-work on other PoW receival', () => co(function*() {
   //   const now = 1474464489;
-- 
GitLab


From 97d0de7336c5f4718c1bec90c089d6226354d258 Mon Sep 17 00:00:00 2001
From: librelois <elois@ifee.fr>
Date: Sun, 3 Dec 2017 00:54:59 +0100
Subject: [PATCH 2/7] [fix] cli option ecoMode : treat cleanly default and
 undefined value

---
 app/cli.ts                            | 1 +
 app/lib/dto/ConfDTO.ts                | 2 +-
 app/modules/prover/index.ts           | 3 +++
 app/modules/prover/lib/blockProver.ts | 2 +-
 app/modules/prover/lib/constants.ts   | 1 +
 index.ts                              | 4 +++-
 6 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/app/cli.ts b/app/cli.ts
index 6a6d3924b..aaae51f89 100644
--- a/app/cli.ts
+++ b/app/cli.ts
@@ -41,6 +41,7 @@ export const ExecuteCommand = () => {
         .option('--addep <endpoint>', 'With `config` command, add given endpoint to the list of endpoints of this node')
         .option('--remep <endpoint>', 'With `config` command, remove given endpoint to the list of endpoints of this node')
 
+        .option('--eco-mode', 'reduce CPU usage for proof-of-work computation')
         .option('--no-eco-mode', 'Do not reduce CPU usage for proof-of-work computation')
         .option('--cpu <percent>', 'Percent of CPU usage for proof-of-work computation', parsePercent)
         .option('--nb-cores <number>', 'Number of cores uses for proof-of-work computation', parseInt)
diff --git a/app/lib/dto/ConfDTO.ts b/app/lib/dto/ConfDTO.ts
index b6ff36a94..e6e750ca0 100644
--- a/app/lib/dto/ConfDTO.ts
+++ b/app/lib/dto/ConfDTO.ts
@@ -91,7 +91,7 @@ export class ConfDTO implements CurrencyConfDTO, KeypairConfDTO, NetworkConfDTO,
     public rmEndpoints: string[],
     public rootoffset: number,
     public upInterval: number,
-    public ecoMode: boolean|true,
+    public ecoMode: boolean|undefined,
     public cpu: number,
     public nbCores: number,
     public prefix: number,
diff --git a/app/modules/prover/index.ts b/app/modules/prover/index.ts
index 856e14237..98e011793 100644
--- a/app/modules/prover/index.ts
+++ b/app/modules/prover/index.ts
@@ -18,6 +18,9 @@ export const ProverDependency = {
     /*********** Permanent prover **************/
     config: {
       onLoading: async (conf:ConfDTO) => {
+        if (conf.ecoMode === null || conf.ecoMode === undefined) {
+          conf.ecoMode = ProverConstants.DEFAULT_ECO_MODE;
+         }
         if (conf.cpu === null || conf.cpu === undefined) {
           conf.cpu = ProverConstants.DEFAULT_CPU;
         }
diff --git a/app/modules/prover/lib/blockProver.ts b/app/modules/prover/lib/blockProver.ts
index 1b6d051c2..03676a8f4 100644
--- a/app/modules/prover/lib/blockProver.ts
+++ b/app/modules/prover/lib/blockProver.ts
@@ -201,7 +201,7 @@ export class BlockProver {
         this.logger.info('Done: #%s, %s in %ss instead of %ss (%s tests, ~%s tests/s)', block.number, proof.hash, (duration / 1000).toFixed(2),
                                                                         this.conf.avgGenTime, testsCount, testsPerSecond.toFixed(2));
         this.logger.info('FOUND proof-of-work with %s leading zeros followed by [0-' + highMark + ']!', nbZeros);
-        if(this.conf.ecoMode && this.conf.nbCores*testsPerSecond > 300) {
+        if(this.conf.ecoMode === true && this.conf.nbCores*testsPerSecond > 300) {
           if(this.conf.nbCores > 1) {
             this.logger.info("Reducing number of CPU cores "+this.conf.nbCores)
             this.conf.nbCores = this.conf.nbCores -1
diff --git a/app/modules/prover/lib/constants.ts b/app/modules/prover/lib/constants.ts
index 0a454d38f..2b8299c33 100644
--- a/app/modules/prover/lib/constants.ts
+++ b/app/modules/prover/lib/constants.ts
@@ -5,6 +5,7 @@ export const ProverConstants = {
   MINIMAL_ZEROS_TO_SHOW_IN_LOGS: 3,
 
   POW_MINIMAL_TO_SHOW: 2,
+  DEFAULT_ECO_MODE: true,
   DEFAULT_CPU: 0.6,
   DEFAULT_PEER_ID: 1,
   MIN_PEER_ID: 1,
diff --git a/index.ts b/index.ts
index daf1b333b..4a8679e7d 100644
--- a/index.ts
+++ b/index.ts
@@ -444,6 +444,7 @@ function commandLineConf(program:any, conf:any = {}) {
   const cli = {
     currency: program.currency,
     ecoMode: program.ecoMode,
+    noEcoMode: program.noEcoMode,
     cpu: program.cpu,
     nbCores: program.nbCores,
     prefix: program.prefix,
@@ -486,7 +487,8 @@ function commandLineConf(program:any, conf:any = {}) {
   // Update the rest of the conf
   if (cli.currency)                             conf.currency = cli.currency;
   if (cli.server.port)                          conf.port = cli.server.port;
-  if (cli.ecoMode)                              conf.ecoMode = cli.ecoMode
+  if (cli.ecoMode)                              conf.ecoMode = true
+  if (cli.noEcoMode)                            conf.ecoMode = false
   if (cli.cpu)                                  conf.cpu = Math.max(0.01, Math.min(1.0, cli.cpu));
   if (cli.prefix)                               conf.prefix = Math.max(ProverConstants.MIN_PEER_ID, Math.min(ProverConstants.MAX_PEER_ID, cli.prefix));
   if (cli.logs.http)                            conf.httplogs = true;
-- 
GitLab


From 42ca7a5a5d0f6bfcc777aa9f2be73335ebd2e0f7 Mon Sep 17 00:00:00 2001
From: cgeek <cem.moreau@gmail.com>
Date: Mon, 4 Dec 2017 17:45:56 +0100
Subject: [PATCH 3/7] [enh] Improve ecomode unit test + fix workers

---
 app/modules/prover/lib/powCluster.ts | 37 +++++++++++++---------------
 test/integration/proof-of-work.js    | 16 ++++++++----
 2 files changed, 28 insertions(+), 25 deletions(-)

diff --git a/app/modules/prover/lib/powCluster.ts b/app/modules/prover/lib/powCluster.ts
index 8e6e65843..15d8d24c3 100644
--- a/app/modules/prover/lib/powCluster.ts
+++ b/app/modules/prover/lib/powCluster.ts
@@ -185,27 +185,24 @@ export class Master {
 
       // Start the salves' job
       this.slaves.forEach((s:any, index) => {
-        if(index < stuff.newPoW.conf.nbCores) {
-          s.worker.send({
-            uuid,
-            command: 'newPoW',
-            value: {
-              block: stuff.newPoW.block,
-              nonceBeginning: s.nonceBeginning,
-              zeros: stuff.newPoW.zeros,
-              highMark: stuff.newPoW.highMark,
-              pair: _.clone(stuff.newPoW.pair),
-              forcedTime: stuff.newPoW.forcedTime,
-              turnDuration: stuff.newPoW.turnDuration,
-              conf: {
-                medianTimeBlocks: stuff.newPoW.conf.medianTimeBlocks,
-                avgGenTime: stuff.newPoW.conf.avgGenTime,
-                cpu: stuff.newPoW.conf.cpu,
-                prefix: stuff.newPoW.conf.prefix
-              }
+        s.worker.send({
+          uuid,
+          command: 'newPoW',
+          value: {
+            block: stuff.newPoW.block,
+            nonceBeginning: s.nonceBeginning,
+            zeros: stuff.newPoW.zeros,
+            highMark: stuff.newPoW.highMark,
+            pair: _.clone(stuff.newPoW.pair),
+            forcedTime: stuff.newPoW.forcedTime,
+            turnDuration: stuff.newPoW.turnDuration,conf: {
+              medianTimeBlocks: stuff.newPoW.conf.medianTimeBlocks,
+              avgGenTime: stuff.newPoW.conf.avgGenTime,
+              cpu: stuff.newPoW.conf.cpu,
+              prefix: stuff.newPoW.conf.prefix
             }
-          })
-        }
+          }
+        })
       })
 
       return await this.currentPromise
diff --git a/test/integration/proof-of-work.js b/test/integration/proof-of-work.js
index dd507167a..4d61810e3 100644
--- a/test/integration/proof-of-work.js
+++ b/test/integration/proof-of-work.js
@@ -36,11 +36,10 @@ const prover = new BlockProver({
 const now = 1474382274 * 1000;
 const MUST_START_WITH_A_ZERO = 16;
 const MUST_START_WITH_TWO_ZEROS = 32;
-const MUST_START_WITH_THREE_ZEROS = 58;
+const MUST_START_WITH_A_ZERO_AND_A_NUMBER = 22
 
 describe("Proof-of-work", function() {
 
-  this.timeout(6*60000)
   it('should be able to find an easy PoW', () => co(function*() {
     let block = yield prover.prove({
       issuer: 'HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd',
@@ -53,12 +52,19 @@ describe("Proof-of-work", function() {
   }));
 
   it('should be reducing cpu when the PoW is too easy for the cpu', () => co(function*() {
+    prover.conf.nbCores = 2
+    prover.conf.cpu = 0.9
+    prover.conf.nbCores.should.equal(2)
+    prover.conf.cpu.should.equal(0.9)
     for(let i=0; i<8; ++i) {
-      let block = yield prover.prove({
+      yield prover.prove({
         issuer: 'HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd',
-        number: i+2
-      }, MUST_START_WITH_THREE_ZEROS, now);
+        number: i+2,
+        now
+      }, MUST_START_WITH_A_ZERO_AND_A_NUMBER, now);
     }
+    prover.conf.nbCores.should.equal(1)
+    prover.conf.cpu.should.be.below(0.9)
   }));
   // Too randomly successing test
   // it('should be able to cancel a proof-of-work on other PoW receival', () => co(function*() {
-- 
GitLab


From 6959f9f19b888ccfc3acdcc6f4fe6320723a007a Mon Sep 17 00:00:00 2001
From: cgeek <cem.moreau@gmail.com>
Date: Mon, 4 Dec 2017 17:50:56 +0100
Subject: [PATCH 4/7] [enh] Put constants in a ProverConstants

---
 app/modules/prover/lib/blockProver.ts | 4 ++--
 app/modules/prover/lib/constants.ts   | 3 +++
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/app/modules/prover/lib/blockProver.ts b/app/modules/prover/lib/blockProver.ts
index 03676a8f4..f3e036770 100644
--- a/app/modules/prover/lib/blockProver.ts
+++ b/app/modules/prover/lib/blockProver.ts
@@ -201,12 +201,12 @@ export class BlockProver {
         this.logger.info('Done: #%s, %s in %ss instead of %ss (%s tests, ~%s tests/s)', block.number, proof.hash, (duration / 1000).toFixed(2),
                                                                         this.conf.avgGenTime, testsCount, testsPerSecond.toFixed(2));
         this.logger.info('FOUND proof-of-work with %s leading zeros followed by [0-' + highMark + ']!', nbZeros);
-        if(this.conf.ecoMode === true && this.conf.nbCores*testsPerSecond > 300) {
+        if(this.conf.ecoMode === true && this.conf.nbCores*testsPerSecond > ProverConstants.ECO_MODE_MINIMAL_TESTS_PER_SECONDS) {
           if(this.conf.nbCores > 1) {
             this.logger.info("Reducing number of CPU cores "+this.conf.nbCores)
             this.conf.nbCores = this.conf.nbCores -1
           }
-          else if(this.conf.cpu > 0.19){
+          else if(this.conf.cpu > ProverConstants.ECO_MODE_MINIMAL_CPU){
             let cpu:number = this.conf.cpu - 0.1
             this.logger.info("Slowing down the CPU to "+cpu)
             this.changeCPU(cpu)
diff --git a/app/modules/prover/lib/constants.ts b/app/modules/prover/lib/constants.ts
index 2b8299c33..3a8d77c70 100644
--- a/app/modules/prover/lib/constants.ts
+++ b/app/modules/prover/lib/constants.ts
@@ -11,6 +11,9 @@ export const ProverConstants = {
   MIN_PEER_ID: 1,
   MAX_PEER_ID: 899, // Due to MAX_SAFE_INTEGER = 9007199254740991 (16 digits, and we use 11 digits for the nonce + 2 digits for core number => 3 digits for the peer, must be below 900)
 
+  ECO_MODE_MINIMAL_TESTS_PER_SECONDS: 300,
+  ECO_MODE_MINIMAL_CPU: 0.19,
+
   NONCE_RANGE: 1000 * 1000 * 1000 * 100,
 
   POW_MAXIMUM_ACCEPTABLE_HANDICAP: 64,
-- 
GitLab


From 93c5b747d2eda594893a45da34bf3cbecc27278f Mon Sep 17 00:00:00 2001
From: cgeek <cem.moreau@gmail.com>
Date: Mon, 4 Dec 2017 17:51:20 +0100
Subject: [PATCH 5/7] [enh] Eco mode should not be by default

---
 app/modules/prover/lib/constants.ts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/modules/prover/lib/constants.ts b/app/modules/prover/lib/constants.ts
index 3a8d77c70..66dbe534b 100644
--- a/app/modules/prover/lib/constants.ts
+++ b/app/modules/prover/lib/constants.ts
@@ -5,7 +5,7 @@ export const ProverConstants = {
   MINIMAL_ZEROS_TO_SHOW_IN_LOGS: 3,
 
   POW_MINIMAL_TO_SHOW: 2,
-  DEFAULT_ECO_MODE: true,
+  DEFAULT_ECO_MODE: false,
   DEFAULT_CPU: 0.6,
   DEFAULT_PEER_ID: 1,
   MIN_PEER_ID: 1,
-- 
GitLab


From 4e8a97cb6377c85c6886d07cacdfb38cb2475151 Mon Sep 17 00:00:00 2001
From: Vincent Rousseau <vincent.rousseau@irstea.fr>
Date: Tue, 9 Jan 2018 15:56:49 +0100
Subject: [PATCH 6/7] Add CPU boost when few bloc of the user in frame

---
 app/lib/computation/BlockchainContext.ts | 10 +++++++
 app/lib/indexer.ts                       |  2 ++
 app/modules/prover/lib/blockProver.ts    | 33 ++++++++++++++++++------
 app/modules/prover/lib/constants.ts      |  2 +-
 4 files changed, 38 insertions(+), 9 deletions(-)

diff --git a/app/lib/computation/BlockchainContext.ts b/app/lib/computation/BlockchainContext.ts
index 426ed2dc8..d8c1344c5 100644
--- a/app/lib/computation/BlockchainContext.ts
+++ b/app/lib/computation/BlockchainContext.ts
@@ -93,6 +93,16 @@ export class BlockchainContext {
     return local_vHEAD.issuerDiff;
   }
 
+  /**
+   * Utility method: gives the number of block in the current frame for a given issuer.
+   * @param issuer The issuer we want.
+   */
+  async getIssuerNbBlockInFrame(issuer: string): Promise<number> {
+    const local_vHEAD = await this.getvHeadCopy({ issuer })
+    let issuerNbBlockInFrame = await indexer.preparePersonalizedPoW(local_vHEAD, this.vHEAD_1, (n:number, m:number, p = "") => this.dal.range(n,m,p), this.conf)
+    return issuerNbBlockInFrame
+  }
+
   setConfDAL(newConf: any, newDAL: any, theBlockchain: DuniterBlockchain, theQuickSynchronizer: QuickSynchronizer): void {
     this.dal = newDAL;
     this.conf = newConf;
diff --git a/app/lib/indexer.ts b/app/lib/indexer.ts
index ddb1cfa99..ea2d70521 100644
--- a/app/lib/indexer.ts
+++ b/app/lib/indexer.ts
@@ -1092,6 +1092,8 @@ export class Indexer {
 
     HEAD.powRemainder = HEAD.issuerDiff  % 16;
     HEAD.powZeros = (HEAD.issuerDiff - HEAD.powRemainder) / 16;
+
+    return nbPersonalBlocksInFrame;
   }
 
   // BR_G19
diff --git a/app/modules/prover/lib/blockProver.ts b/app/modules/prover/lib/blockProver.ts
index f3e036770..ce45c9f68 100644
--- a/app/modules/prover/lib/blockProver.ts
+++ b/app/modules/prover/lib/blockProver.ts
@@ -192,6 +192,15 @@ export class BlockProver {
       });
       if (!result) {
         this.logger.info('GIVEN proof-of-work for block#%s with %s leading zeros followed by [0-' + highMark + ']! stop PoW for %s', block.number, nbZeros, this.pair && this.pair.pub.slice(0,6));
+        let selfNbBlockInFrame = await this.server.getBcContext().getIssuerNbBlockInFrame(this.server.PeeringService.selfPubkey)
+        if(this.conf.ecoMode === true) {
+          let selfNbBlockInFrame = await this.server.getBcContext().getIssuerNbBlockInFrame(this.server.PeeringService.selfPubkey)
+          if(selfNbBlockInFrame < 2) {
+            this.changeCPU(1)
+            this.conf.nbCores = this.server.conf.nbCores
+            this.logger.info("Boost number of CPU cores "+this.conf.nbCores+" with only "+selfNbBlockInFrame+" block member in frame")
+          }
+        }
         throw 'Proof-of-work computation canceled because block received';
       } else {
         const proof = result.block;
@@ -201,15 +210,23 @@ export class BlockProver {
         this.logger.info('Done: #%s, %s in %ss instead of %ss (%s tests, ~%s tests/s)', block.number, proof.hash, (duration / 1000).toFixed(2),
                                                                         this.conf.avgGenTime, testsCount, testsPerSecond.toFixed(2));
         this.logger.info('FOUND proof-of-work with %s leading zeros followed by [0-' + highMark + ']!', nbZeros);
-        if(this.conf.ecoMode === true && this.conf.nbCores*testsPerSecond > ProverConstants.ECO_MODE_MINIMAL_TESTS_PER_SECONDS) {
-          if(this.conf.nbCores > 1) {
-            this.logger.info("Reducing number of CPU cores "+this.conf.nbCores)
-            this.conf.nbCores = this.conf.nbCores -1
+        if(this.conf.ecoMode === true) {
+          let selfNbBlockInFrame = await this.server.getBcContext().getIssuerNbBlockInFrame(this.server.PeeringService.selfPubkey)
+          if(selfNbBlockInFrame < 2) {
+            this.changeCPU(1)
+            this.conf.nbCores = this.server.conf.nbCores
+            this.logger.info("Boost number of CPU cores "+this.conf.nbCores+" with only "+selfNbBlockInFrame+" block member in frame")
           }
-          else if(this.conf.cpu > ProverConstants.ECO_MODE_MINIMAL_CPU){
-            let cpu:number = this.conf.cpu - 0.1
-            this.logger.info("Slowing down the CPU to "+cpu)
-            this.changeCPU(cpu)
+          else if(this.conf.nbCores*testsPerSecond > ProverConstants.ECO_MODE_MINIMAL_TESTS_PER_SECONDS) {
+            if(this.conf.nbCores > 1) {
+              this.logger.info("Reducing number of CPU cores "+this.conf.nbCores)
+              this.conf.nbCores = this.conf.nbCores -1
+            }
+            else if(this.conf.cpu > ProverConstants.ECO_MODE_MINIMAL_CPU){
+              let cpu:number = this.conf.cpu - 0.1
+              this.logger.info("Slowing down the CPU to "+cpu)
+              this.changeCPU(cpu)
+            }
           }
         }
         return BlockDTO.fromJSONObject(proof)
diff --git a/app/modules/prover/lib/constants.ts b/app/modules/prover/lib/constants.ts
index 66dbe534b..3a8d77c70 100644
--- a/app/modules/prover/lib/constants.ts
+++ b/app/modules/prover/lib/constants.ts
@@ -5,7 +5,7 @@ export const ProverConstants = {
   MINIMAL_ZEROS_TO_SHOW_IN_LOGS: 3,
 
   POW_MINIMAL_TO_SHOW: 2,
-  DEFAULT_ECO_MODE: false,
+  DEFAULT_ECO_MODE: true,
   DEFAULT_CPU: 0.6,
   DEFAULT_PEER_ID: 1,
   MIN_PEER_ID: 1,
-- 
GitLab


From 63a7f4b75a6e19eb3bc9ae81241edb5b597a5f65 Mon Sep 17 00:00:00 2001
From: Vincent Rousseau <vincent.rousseau@irstea.fr>
Date: Thu, 11 Jan 2018 13:43:43 +0100
Subject: [PATCH 7/7] Add and remove workers during eco mode

---
 app/modules/prover/lib/blockProver.ts | 41 ++++++++++----
 app/modules/prover/lib/engine.ts      | 13 +++--
 app/modules/prover/lib/powCluster.ts  | 82 +++++++++++++++++----------
 3 files changed, 91 insertions(+), 45 deletions(-)

diff --git a/app/modules/prover/lib/blockProver.ts b/app/modules/prover/lib/blockProver.ts
index 11ff17da0..a94a03cfe 100644
--- a/app/modules/prover/lib/blockProver.ts
+++ b/app/modules/prover/lib/blockProver.ts
@@ -48,6 +48,14 @@ export class WorkerFarm {
     return this.theEngine.getNbWorkers()
   }
 
+  reduceNbCores() {
+    return this.theEngine.reduceNbCores()
+  }
+
+  boostCPU(){
+    return this.theEngine.boostCPU()
+  }
+
   changeCPU(cpu:any) {
     return this.theEngine.setConf({ cpu })
   }
@@ -194,13 +202,12 @@ export class BlockProver {
       });
       if (!result) {
         this.logger.info('GIVEN proof-of-work for block#%s with %s leading zeros followed by [0-' + highMark + ']! stop PoW for %s', block.number, nbZeros, this.pair && this.pair.pub.slice(0,6));
-        let selfNbBlockInFrame = await this.server.getBcContext().getIssuerNbBlockInFrame(this.server.PeeringService.selfPubkey)
         if(this.conf.ecoMode === true) {
           let selfNbBlockInFrame = await this.server.getBcContext().getIssuerNbBlockInFrame(this.server.PeeringService.selfPubkey)
           if(selfNbBlockInFrame < 2) {
-            this.changeCPU(1)
-            this.conf.nbCores = this.server.conf.nbCores
-            this.logger.info("Boost number of CPU cores "+this.conf.nbCores+" with only "+selfNbBlockInFrame+" block member in frame")
+            this.boostCPU()
+            this.conf.nbCores = powFarm.nbWorkers
+            this.logger.info("Boost number of CPU cores "+powFarm.nbWorkers+" with only "+selfNbBlockInFrame+" block member in frame")
           }
         }
         throw 'Proof-of-work computation canceled because block received';
@@ -214,14 +221,15 @@ export class BlockProver {
         if(this.conf.ecoMode === true) {
           let selfNbBlockInFrame = await this.server.getBcContext().getIssuerNbBlockInFrame(this.server.PeeringService.selfPubkey)
           if(selfNbBlockInFrame < 2) {
-            this.changeCPU(1)
-            this.conf.nbCores = this.server.conf.nbCores
-            this.logger.info("Boost number of CPU cores "+this.conf.nbCores+" with only "+selfNbBlockInFrame+" block member in frame")
+            this.boostCPU()
+            this.conf.nbCores = powFarm.nbWorkers
+            this.logger.info("Boost number of CPU cores "+powFarm.nbWorkers+" with only "+selfNbBlockInFrame+" block member in frame")
           }
-          else if(this.conf.nbCores*testsPerSecond > ProverConstants.ECO_MODE_MINIMAL_TESTS_PER_SECONDS) {
-            if(this.conf.nbCores > 1) {
-              this.logger.info("Reducing number of CPU cores "+this.conf.nbCores)
-              this.conf.nbCores = this.conf.nbCores -1
+          else if(testsPerSecond > ProverConstants.ECO_MODE_MINIMAL_TESTS_PER_SECONDS) {
+            if(powFarm.nbWorkers > 1) {
+              this.logger.info("Reducing number of CPU cores "+powFarm.nbWorkers)
+              this.reduceNbCores()
+              this.conf.nbCores = powFarm.nbWorkers
             }
             else if(this.conf.cpu > ProverConstants.ECO_MODE_MINIMAL_CPU){
               let cpu:number = this.conf.cpu - 0.1
@@ -235,6 +243,17 @@ export class BlockProver {
     })()
   };
 
+  async reduceNbCores() {
+    const farm = await this.getWorker()
+    return farm.reduceNbCores()
+  }
+
+  async boostCPU() {
+    this.conf.cpu = 1.0
+    const farm = await this.getWorker()
+    return farm.boostCPU()
+  }
+
   async changeCPU(cpu:number) {
     this.conf.cpu = Math.max(0.01, Math.min(1.0, cpu));
     const farm = await this.getWorker()
diff --git a/app/modules/prover/lib/engine.ts b/app/modules/prover/lib/engine.ts
index 6ab1ca645..64bd629f3 100644
--- a/app/modules/prover/lib/engine.ts
+++ b/app/modules/prover/lib/engine.ts
@@ -12,15 +12,12 @@ if(debug) {
 
 export class PowEngine {
 
-  private nbWorkers:number
   private cluster:PowCluster
   readonly id:number
 
   constructor(private conf:ConfDTO, logger:any) {
-
     // We use as much cores as available, but not more than CORES_MAXIMUM_USE_IN_PARALLEL
-    this.nbWorkers = conf.nbCores
-    this.cluster = new PowCluster(this.nbWorkers, logger)
+    this.cluster = new PowCluster(conf.nbCores, logger)
     this.id = this.cluster.clusterId
   }
 
@@ -41,6 +38,14 @@ export class PowEngine {
     return this.cluster.cancelWork()
   }
 
+  reduceNbCores() {
+    return this.cluster.removeSlave()
+  }
+
+  boostCPU() {
+    return this.cluster.boostCPU()
+  }
+
   setConf(value:any) {
     return this.cluster.changeConf(value)
   }
diff --git a/app/modules/prover/lib/powCluster.ts b/app/modules/prover/lib/powCluster.ts
index d0c64c4e4..fc3821043 100644
--- a/app/modules/prover/lib/powCluster.ts
+++ b/app/modules/prover/lib/powCluster.ts
@@ -35,6 +35,7 @@ export class Master {
   logger:any
   onInfoCallback:any
   workersOnline:Promise<any>[]
+  maxNbCores:number = Math.min(ProverConstants.CORES_MAXIMUM_USE_IN_PARALLEL, require('os').cpus().length)
 
   constructor(private nbCores:number, logger:any) {
     this.clusterId = clusterId++
@@ -65,6 +66,56 @@ export class Master {
     // this.logger.debug(`ENGINE c#${this.clusterId}#${this.slavesMap[worker.id].index}:`, message)
   }
 
+  createSlave(index:number) {
+    const nodejsWorker = cluster.fork()
+    const worker = new PowWorker(nodejsWorker, message => {
+      this.onWorkerMessage(index, message)
+    }, () => {
+      this.logger.info(`[online] worker c#${this.clusterId}#w#${index}`)
+      worker.sendConf({
+        command: 'conf',
+        value: this.conf
+      })
+    }, (code:any, signal:any) => {
+      this.logger.info(`worker ${worker.pid} died with code ${code} and signal ${signal}`)
+    })
+
+    this.logger.info(`Creating worker c#${this.clusterId}#w#${nodejsWorker.id}`)
+    const slave = {
+
+      // The Node.js worker
+      worker,
+
+      // Inner identifier
+      index,
+
+      // Worker ready
+      online: worker.online,
+
+      // Each worker has his own chunk of possible nonces
+      nonceBeginning: this.nbCores === 1 ? 0 : (index + 1) * ProverConstants.NONCE_RANGE
+    }
+    this.slavesMap[nodejsWorker.id] = slave
+    return slave
+  }
+
+  boostCPU() {
+    if(this.nbWorkers < this.maxNbCores) {
+      while(this.nbWorkers < this.maxNbCores) {
+        this.slaves.push(this.createSlave(this.nbWorkers))
+      }
+    }
+    let conf:any = {cpu: 1}
+    this.changeConf(conf)
+  }
+
+  async removeSlave() {
+    let nb_workers = this.nbWorkers
+    await this.slaves[nb_workers-1].worker.kill()
+    this.slaves.pop()
+    this.logger.info('Remove slave number '+ (nb_workers-1))
+  }
+
   /*****************
    * CLUSTER METHODS
    ****************/
@@ -77,36 +128,7 @@ export class Master {
     })
 
     this.slaves = Array.from({ length: this.nbCores }).map((value, index) => {
-      const nodejsWorker = cluster.fork()
-      const worker = new PowWorker(nodejsWorker, message => {
-        this.onWorkerMessage(index, message)
-      }, () => {
-        this.logger.info(`[online] worker c#${this.clusterId}#w#${index}`)
-        worker.sendConf({
-          command: 'conf',
-          value: this.conf
-        })
-      }, (code:any, signal:any) => {
-        this.logger.info(`worker ${worker.pid} died with code ${code} and signal ${signal}`)
-      })
-
-      this.logger.info(`Creating worker c#${this.clusterId}#w#${nodejsWorker.id}`)
-      const slave = {
-
-        // The Node.js worker
-        worker,
-
-        // Inner identifier
-        index,
-
-        // Worker ready
-        online: worker.online,
-
-        // Each worker has his own chunk of possible nonces
-        nonceBeginning: this.nbCores === 1 ? 0 : (index + 1) * ProverConstants.NONCE_RANGE
-      }
-      this.slavesMap[nodejsWorker.id] = slave
-      return slave
+      return this.createSlave(index)
     })
 
     this.workersOnline = this.slaves.map((s) => s.online)
-- 
GitLab