diff --git a/app/controllers/blockchain.js b/app/controllers/blockchain.js
index da748d54d01b1ae4a204ebe976b0664ca6a6118d..b3a44f530b4c7cef680d3a934433cc5e295fe716 100644
--- a/app/controllers/blockchain.js
+++ b/app/controllers/blockchain.js
@@ -90,10 +90,10 @@ function BlockchainBinding (server) {
     if (current) {
       nextBlockNumber = current ? current.number + 1 : 0;
     }
-    let nbZeros = yield globalValidator(conf, blockchainDao(null, server.dal)).getTrialLevel(idty.pubkey);
+    let difficulty = yield globalValidator(conf, blockchainDao(null, server.dal)).getTrialLevel(idty.pubkey);
     return {
       "block": nextBlockNumber,
-      "level": nbZeros
+      "level": difficulty
     };
   });
 
@@ -104,10 +104,10 @@ function BlockchainBinding (server) {
     for (let i = 0, len = issuers.length; i < len; i++) {
       let issuer = issuers[i];
       let member = yield server.dal.getWrittenIdtyByPubkey(issuer);
-      let level = yield globalValidator(conf, blockchainDao(null, server.dal)).getTrialLevel(member.pubkey);
+      let difficulty = yield globalValidator(conf, blockchainDao(null, server.dal)).getTrialLevel(member.pubkey);
       difficulties.push({
         uid: member.uid,
-        level: level
+        level: difficulty
       });
     }
     return {
diff --git a/app/lib/constants.js b/app/lib/constants.js
index ceda6b1557bd729f6a80aa99db150b501803c932..5ddba47fd615fb3589e46e803277c361c382b5fa 100644
--- a/app/lib/constants.js
+++ b/app/lib/constants.js
@@ -159,7 +159,13 @@ module.exports = {
   },
   PROOF_OF_WORK: {
     EVALUATION: 200,
-    RELEASE_MEMORY: 10000
+    RELEASE_MEMORY: 10000,
+    UPPER_BOUND: {
+      LEVEL_0: '9A-F',
+      LEVEL_1: '7',
+      LEVEL_2: '3',
+      LEVEL_3: '1'
+    }
   },
 
   DURATIONS: {
diff --git a/app/lib/globalValidator.js b/app/lib/globalValidator.js
index 231a42b6b6a349f8ae2c4413fe199980ce7d8ece..22b8024e9c3a04109f9ba471be46059083ebe88d 100644
--- a/app/lib/globalValidator.js
+++ b/app/lib/globalValidator.js
@@ -8,6 +8,7 @@ var crypto        = require('./crypto');
 var moment        = require('moment');
 var util          = require('util');
 var stream        = require('stream');
+var constants     = require('./constants');
 var Block         = require('../lib/entity/block');
 var Identity      = require('../lib/entity/identity');
 var Membership    = require('../lib/entity/membership');
@@ -400,9 +401,9 @@ function GlobalValidator (conf, dao) {
           var lastDistant = yield dao.getBlock(Math.max(0, blockNumber - conf.dtDiffEval));
           // Compute PoWMin value
           var duration = medianTime - lastDistant.medianTime;
-          var speed = (conf.dtDiffEval * 1.0) / (duration * 1.0);
-          var maxGenTime = conf.avgGenTime * 4;
-          var minGenTime = conf.avgGenTime / 4;
+          var speed = parseFloat(conf.dtDiffEval) / duration;
+          var maxGenTime = Math.ceil(conf.avgGenTime * Math.sqrt(2));
+          var minGenTime = Math.floor(conf.avgGenTime / Math.sqrt(2));
           var maxSpeed = 1.0 / minGenTime;
           var minSpeed = 1.0 / maxGenTime;
           // logger.debug('Current speed is', speed, '(' + conf.dtDiffEval + '/' + duration + ')', 'and must be [', minSpeed, ';', maxSpeed, ']');
@@ -430,14 +431,23 @@ function GlobalValidator (conf, dao) {
       function (next){
         getTrialLevel(block.issuer, next);
       },
-      function (nbZeros, next){
-        var powRegexp = new RegExp('^0{' + nbZeros + ',}');
-        if (!block.hash.match(powRegexp))
-          next('Wrong proof-of-work level: given ' + block.hash.match(/^0*/)[0].length + ' zeros, required was ' + nbZeros + ' zeros');
+      function (difficulty, next){
+        var remainder = difficulty % 4;
+        var nbZerosReq = Math.max(0, (difficulty - remainder) / 4);
+        var highMark = remainder == 3 ? constants.PROOF_OF_WORK.UPPER_BOUND.LEVEL_3
+          : (remainder == 2 ? constants.PROOF_OF_WORK.UPPER_BOUND.LEVEL_2
+          : (remainder == 1 ? constants.PROOF_OF_WORK.UPPER_BOUND.LEVEL_1
+          : constants.PROOF_OF_WORK.UPPER_BOUND.LEVEL_0));
+        var powRegexp = new RegExp('^0{' + nbZerosReq + '}' + '[0-' + highMark + ']');
+        if (!block.hash.match(powRegexp)) {
+          var givenZeros = Math.max(0, Math.min(nbZerosReq, block.hash.match(/^0*/)[0].length));
+          var c = block.hash.substr(givenZeros, 1);
+          next('Wrong proof-of-work level: given ' + givenZeros + ' zeros and \'' + c + '\', required was ' + nbZerosReq + ' zeros and an hexa char between [0-' + highMark + ']');
+        }
         else {
           next();
         }
-      },
+      }
     ], done);
   }
 
@@ -656,8 +666,8 @@ function GlobalValidator (conf, dao) {
             function (issuers, next) {
               var nbPreviousIssuers = _(_(issuers).uniq()).without(issuer).length;
               var nbBlocksSince = current.number - last.number;
-              var nbZeros = Math.max(powMin, powMin * Math.floor(percentRot * (1 + nbPreviousIssuers) / (1 + nbBlocksSince)));
-              next(null, nbZeros);
+              var difficulty = Math.max(powMin, powMin * Math.floor(percentRot * (1 + nbPreviousIssuers) / (1 + nbBlocksSince)));
+              next(null, difficulty);
             }
           ], next);
         }
diff --git a/app/lib/localValidator.js b/app/lib/localValidator.js
index 3e61eecb5b29fb9940473e045f4fa77a00f1a136..3fde05fbad20b06da5c0122633de48b40e06d6a8 100644
--- a/app/lib/localValidator.js
+++ b/app/lib/localValidator.js
@@ -111,7 +111,7 @@ function LocalValidator (conf) {
   };
 
   function maxAcceleration () {
-    return conf.avgGenTime * 4 * (Math.ceil((conf.medianTimeBlocks + 1) / 2));
+    return Math.ceil(conf.avgGenTime * Math.sqrt(2)) * (Math.ceil((conf.medianTimeBlocks + 1) / 2) + 1);
   }
 
   this.checkSingleMembershipSignature = checkSingleMembershipSignature;
@@ -130,7 +130,7 @@ function LocalValidator (conf) {
   });
 
   this.checkProofOfWork = check(function (block, done) {
-    var powRegexp = new RegExp('^0{' + block.powMin + '}');
+    var powRegexp = new RegExp('^0{' + Math.floor(block.powMin / 4) + '}');
     if (!block.hash.match(powRegexp))
       done('Not a proof-of-work');
     else
@@ -165,7 +165,6 @@ function LocalValidator (conf) {
   this.checkBlockTimes = check(function (block, done) {
     var time = parseInt(block.time);
     var medianTime = parseInt(block.medianTime);
-    var maxGenTime = conf.avgGenTime * 4;
     if (block.number > 0 && (time < medianTime || time > medianTime + maxAcceleration()))
       done('A block must have its Time between MedianTime and MedianTime + ' + maxAcceleration());
     else if (block.number == 0 && time != medianTime)
diff --git a/app/lib/proof.js b/app/lib/proof.js
index 0f67316ff070eaa58b81aedc090af42ebff08a43..4ace9e8ceff501d1bb0ebd519537d4ef7c7b55e5 100644
--- a/app/lib/proof.js
+++ b/app/lib/proof.js
@@ -22,6 +22,7 @@ process.on('message', function(stuff){
   var pair = stuff.pair;
   var forcedTime = stuff.forcedTime;
   var cpu = conf.cpu || 1;
+  var highMark = stuff.highMark;
   async.waterfall([
     function(next) {
       if (signatureFunc)
@@ -31,17 +32,17 @@ process.on('message', function(stuff){
     },
     function(sigFunc, next) {
       signatureFunc = sigFunc;
-      var powRegexp = new RegExp('^0{' + nbZeros + '}[^0]');
-      var lowPowRegexp = new RegExp('^0{' + (nbZeros-1) + '}[^0]');
-      var verylowPowRegexp = new RegExp('^0{' + (nbZeros-2) + '}[^0]');
+      var powRegexp = new RegExp('^0{' + nbZeros + '}' + '[0-' + highMark + ']');
+      var lowPowRegexp = new RegExp('^0{' + (nbZeros) + '}[^0]');
+      var verylowPowRegexp = new RegExp('^0{' + (nbZeros - 1) + '}[^0]');
       var pow = "", sig = "", raw = "";
 
       // Time must be = [medianTime; medianTime + minSpeed]
       block.time = getBlockTime(block, conf, forcedTime);
       // Test CPU speed
-      var testsPerSecond = nbZeros > 0 ? computeSpeed(block, sigFunc) : 1;
+      var testsPerSecond = nbZeros == 0 && highMark == '9A-F' ? 1 : computeSpeed(block, sigFunc);
       var testsPerRound = Math.max(Math.round(testsPerSecond * cpu), 1);
-      process.send({ found: false, testsPerSecond: testsPerSecond, testsPerRound: testsPerRound });
+      process.send({ found: false, testsPerSecond: testsPerSecond, testsPerRound: testsPerRound, nonce: block.nonce });
       // Really start now
       var testsCount = 0;
       if (nbZeros == 0) {
diff --git a/app/service/BlockchainService.js b/app/service/BlockchainService.js
index 76ba608d8181feb22e451cf02a6a81620c130a69..4269d6e8617274c240eaff9776d03717082d38d5 100644
--- a/app/service/BlockchainService.js
+++ b/app/service/BlockchainService.js
@@ -1044,7 +1044,14 @@ function BlockchainService (conf, mainDAL, pair) {
   }
   var powWorker;
 
-  this.prove = function (block, sigFunc, nbZeros, done, forcedTime) {
+  this.prove = function (block, sigFunc, difficulty, done, forcedTime) {
+
+    var remainder = difficulty % 4;
+    var nbZeros = (difficulty - remainder) / 4;
+    var highMark = remainder == 3 ? constants.PROOF_OF_WORK.UPPER_BOUND.LEVEL_3
+      : (remainder == 2 ? constants.PROOF_OF_WORK.UPPER_BOUND.LEVEL_2
+      : (remainder == 1 ?constants.PROOF_OF_WORK.UPPER_BOUND.LEVEL_1
+      : constants.PROOF_OF_WORK.UPPER_BOUND.LEVEL_0));
 
     return Q.Promise(function(resolve, reject){
       if (!powWorker) {
@@ -1052,7 +1059,7 @@ function BlockchainService (conf, mainDAL, pair) {
       }
       if (block.number == 0) {
         // On initial block, difficulty is the one given manually
-        block.powMin = nbZeros;
+        block.powMin = difficulty;
       }
       // Start
       powWorker.setOnPoW(function(err, powBlock) {
@@ -1066,12 +1073,12 @@ function BlockchainService (conf, mainDAL, pair) {
       });
 
       block.nonce = 0;
-      powWorker.powProcess.send({ conf: conf, block: block, zeros: nbZeros, forcedTime: forcedTime,
+      powWorker.powProcess.send({ conf: conf, block: block, zeros: nbZeros, highMark: highMark, forcedTime: forcedTime,
         pair: {
           secretKeyEnc: base58.encode(pair.secretKey)
         }
       });
-      logger.info('Generating proof-of-work of block #%s with %s leading zeros... (CPU usage set to %s%)', block.number, nbZeros, (conf.cpu*100).toFixed(0));
+      logger.info('Generating proof-of-work with %s leading zeros followed by [0-' + highMark + ']... (CPU usage set to %s%)', nbZeros, (conf.cpu * 100).toFixed(0));
     });
   };
 
diff --git a/doc/Protocol.md b/doc/Protocol.md
index b18541ff129c3b89bdc29bae93a82cae453abad9..eb1be7ea0e7914b939b5a07a3ad73476bf76fbd7 100644
--- a/doc/Protocol.md
+++ b/doc/Protocol.md
@@ -692,9 +692,9 @@ percentRot  | The percent of previous issuers to reach for personalized difficul
 Variable  | Meaning
 --------- | ----
 members   | Synonym of `members(t = now)`, `wot(t)`, `community(t)` targeting the keys whose last valid (non-expired) membership is either in `Joiners` or `Actives`.
-maxGenTime  | `= avgGenTime * 4`
-minGenTime  | `= avgGenTime / 4`
-maxAcceleration | `= maxGenTime * CEIL((medianTimeBlocks + 1) / 2)`
+maxGenTime  | `= CEIL(avgGenTime * √2)`
+minGenTime  | `= FLOOR(avgGenTime / √2)`
+maxAcceleration | `= maxGenTime * (CEIL((medianTimeBlocks + 1) / 2) + 1)`
 
 ## Processing
 
diff --git a/test/data/blocks.js b/test/data/blocks.js
index a72500fea7f54029991ec9e7abc0c7c11c459868..ac23f06e0cfbf111f9501b0c7a741605cc62f637 100644
--- a/test/data/blocks.js
+++ b/test/data/blocks.js
@@ -1636,7 +1636,7 @@ module.exports = {
     "Version: 1\n" +
     "Type: Block\n" +
     "Currency: beta_brousouf\n" +
-    "Nonce: 11\n" +
+    "Nonce: 12\n" +
     "Number: 3\n" +
     "PoWMin: 1\n" +
     "Time: 1411776000\n" +
diff --git a/test/fast/block/block_global.js b/test/fast/block/block_global.js
index 87e0b205bf5912f1143ec2017bbb37cce452e916..8c661a997710aa140ead45c52d694119985efe6e 100644
--- a/test/fast/block/block_global.js
+++ b/test/fast/block/block_global.js
@@ -189,17 +189,17 @@ describe("Block global coherence:", function(){
 
   it('a block not starting with a leading zero should fail', test('checkProofOfWork', blocks.NO_LEADING_ZERO, function (err) {
     should.exist(err);
-    err.should.equal('Wrong proof-of-work level: given 0 zeros, required was 1 zeros');
+    err.should.equal('Wrong proof-of-work level: given 0 zeros and \'C\', required was 0 zeros and an hexa char between [0-7]');
   }));
 
   it('a block requiring 2 leading zeros but providing less should fail', test('checkProofOfWork', blocks.REQUIRES_7_LEADING_ZEROS, function (err) {
     should.exist(err);
-    err.should.equal('Wrong proof-of-work level: given 0 zeros, required was 2 zeros');
+    err.should.equal('Wrong proof-of-work level: given 0 zeros and \'6\', required was 0 zeros and an hexa char between [0-3]');
   }));
 
   it('a block requiring 1 leading zeros but providing less should fail', test('checkProofOfWork', blocks.REQUIRES_6_LEADING_ZEROS, function (err) {
     should.exist(err);
-    err.should.equal('Wrong proof-of-work level: given 0 zeros, required was 1 zeros');
+    err.should.equal('Wrong proof-of-work level: given 0 zeros and \'C\', required was 0 zeros and an hexa char between [0-7]');
   }));
 
   it('a block requiring 1 leading zeros as first block of newcomer should succeed', test('checkProofOfWork', blocks.FIRST_BLOCK_OF_NEWCOMER, function (err) {
@@ -208,7 +208,7 @@ describe("Block global coherence:", function(){
 
   it('a block requiring 40 leading zeros as second block of newcomer should fail', test('checkProofOfWork', blocks.SECOND_BLOCK_OF_NEWCOMER, function (err) {
     should.exist(err);
-    err.should.equal('Wrong proof-of-work level: given 0 zeros, required was 40 zeros');
+    err.should.equal('Wrong proof-of-work level: given 0 zeros and \'6\', required was 10 zeros and an hexa char between [0-9A-F]');
   }));
 
   it('a root block should not fail for time reason', test('checkTimes', blocks.WRONG_ROOT_DATES, function (err) {
diff --git a/test/fast/block/block_local.js b/test/fast/block/block_local.js
index 0ccfeffa8c49f584aff2fb9669d86e83f4b1e38b..3c0b8f3397d7fdf950f142508401f9d74ab3061e 100644
--- a/test/fast/block/block_local.js
+++ b/test/fast/block/block_local.js
@@ -10,12 +10,13 @@ var Block          = require('../../../app/lib/entity/block');
 var Configuration  = require('../../../app/lib/entity/configuration');
 
 var conf = Configuration.statics.complete({
-  sigDelay: 365.25*24*3600, // 1 year
+  sigDelay: 365.25 * 24 * 3600, // 1 year
   sigQty: 1,
   powZeroMin: 1,
   powPeriod: 18,
   incDateMin: 10,
   avgGenTime: 60,
+  medianTimeBlocks: 20,
   dt: 100,
   ud0: 100,
   c: 0.1
@@ -76,12 +77,12 @@ describe("Block local coherence", function(){
     }));
 
     it('a block with wrong date (in past)', test('checkBlockTimes', blocks.WRONG_DATE_LOWER, function (err, done) {
-      assert.equal(err, 'A block must have its Time between MedianTime and MedianTime + 2640');
+      assert.equal(err, 'A block must have its Time between MedianTime and MedianTime + 1020');
       done();
     }));
 
     it('a block with wrong date (in future, but too far)', test('checkBlockTimes', blocks.WRONG_DATE_HIGHER_BUT_TOO_HIGH, function (err, done) {
-      assert.equal(err, 'A block must have its Time between MedianTime and MedianTime + 2640');
+      assert.equal(err, 'A block must have its Time between MedianTime and MedianTime + 1020');
       done();
     }));