diff --git a/Cargo.lock b/Cargo.lock
index a56b5b7923bd05f566a13dcfd200c065feef7522..c22bb19bf1ea8829d83603e313f2a3b609c270a8 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -577,6 +577,7 @@ dependencies = [
  "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)",
  "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "unwrap 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1327,6 +1328,38 @@ dependencies = [
  "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "num"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-complex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-iter 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-rational 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "num-bigint"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "num-complex"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "num-integer"
 version = "0.1.41"
@@ -1336,6 +1369,27 @@ dependencies = [
  "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "num-iter"
+version = "0.1.39"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "num-rational"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "num-traits"
 version = "0.2.8"
@@ -2611,7 +2665,12 @@ dependencies = [
 "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88"
 "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945"
 "checksum nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6"
+"checksum num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cf4825417e1e1406b3782a8ce92f4d53f26ec055e3622e1881ca8e9f5f9e08db"
+"checksum num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f9c3f34cdd24f334cb265d9bf8bfa8a241920d026916785747a92f0e55541a1a"
+"checksum num-complex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fcb0cf31fb3ff77e6d2a6ebd6800df7fdcd106f2ad89113c9130bcd07f93dffc"
 "checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09"
+"checksum num-iter 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "76bd5272412d173d6bf9afdf98db8612bbabc9a7a830b7bfc9c188911716132e"
+"checksum num-rational 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f2885278d5fe2adc2f75ced642d52d879bffaceb5a2e0b1d4309ffdfb239b454"
 "checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32"
 "checksum num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273"
 "checksum numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef"
diff --git a/lib/modules-lib/bc-db-reader/Cargo.toml b/lib/modules-lib/bc-db-reader/Cargo.toml
index e23d3c150523ed07643a7c6e95209790aedb2f7d..c5bff6033995025fc64f8bb5fbe58d667df271cb 100644
--- a/lib/modules-lib/bc-db-reader/Cargo.toml
+++ b/lib/modules-lib/bc-db-reader/Cargo.toml
@@ -26,6 +26,7 @@ maplit = "1.0.1"
 fnv = "1.0.6"
 serde = { version = "1.0.*", features = ["derive"] }
 unwrap = "1.2.1"
+num = "0.2"
 
 [dev-dependencies]
 dup-crypto-tests-tools = { path = "../../tests-tools/crypto-tests-tools" }
diff --git a/lib/modules-lib/bc-db-reader/src/current_frame.rs b/lib/modules-lib/bc-db-reader/src/current_frame.rs
index a69091ea0d559dd161b65295bb2886273ffe62ad..07e3259916ab50c705cc03a90d90b1f113169fe0 100644
--- a/lib/modules-lib/bc-db-reader/src/current_frame.rs
+++ b/lib/modules-lib/bc-db-reader/src/current_frame.rs
@@ -17,8 +17,11 @@
 
 //use crate::constants::*;
 use crate::*;
+extern crate num;
+use dubp_common_doc::BlockNumber;
 use durs_dbs_tools::DbError;
 use durs_wot::WotId;
+use num::Float;
 
 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
 /// Describe a member in current frame
@@ -54,3 +57,95 @@ pub fn get_member_diffi<DB: DbReadable, R: DbReader>(
 ) -> Result<PersonalDifficulty, DbError> {
     unimplemented!();
 }
+
+/// calcule la difficulté personnalisée à partir des données prêtes à l'emploi
+/// reference dans le protocol : https://github.com/duniter/duniter/blob/master/doc/Protocol.md#br_g18---headpowzeros-and-headpowremainder
+pub fn compute_personal_difficulty(
+    nb_member_in_frame: usize,
+    last_personal_block_number: BlockNumber,
+    current_block_number: BlockNumber,
+    nb_personal_blocks_in_frame: usize,
+    median_of_blocks_in_frame: usize,
+) -> PersonalDifficulty {
+    PersonalDifficulty {
+        exclusion_factor: exclusion_factor(
+            nb_member_in_frame,
+            current_block_number.0 - last_personal_block_number.0,
+        ),
+        handicap: handicap(nb_personal_blocks_in_frame, median_of_blocks_in_frame),
+    }
+}
+
+/// calcule le facteur d'exclusion à partir des membres de la fenêtres courante et du dernier block du membre concerné
+/// ne gère pas le cas où le membre n'est pas dans la fenêtre courante
+///
+/// nb_member_in_frame : la valeur du champ issuersCount du dernier bloc trouvé par le membre
+/// nb_blocks_since : le nombre de blocs trouvés par le reste du réseau depuis que le membre considéré a trouvé son dernier bloc
+/// exclusion_factor = MAX [ 1 ; FLOOR (0.67 * nb_member_in_frame / (1 + nb_blocks_since)) ]
+///
+/// reference dans le protocol : https://github.com/duniter/duniter/blob/master/doc/Protocol.md#br_g18---headpowzeros-and-headpowremainder
+pub fn exclusion_factor(nb_member_in_frame: usize, nb_blocks_since: u32) -> usize {
+    std::cmp::max(
+        1,
+        (0.67 * (nb_member_in_frame as f64 / (1 + nb_blocks_since) as f64)).floor() as usize,
+    )
+}
+
+/// handicap calcule le handicap d'un membre à partir du nombre de blocs qu'il a caclulé dans la fenêtre courante et du
+/// nombre median de blocs écrits par les membres dans la fenêtre courante.
+/// ne gère pas le cas où le membre n'est pas dans la fenêtre courante
+///
+/// nb_personal_blocks_in_frame : le nombre de blocs écrits par le membre considéré dans la fenêtre courante
+/// median_of_blocks_in_frame : le nombre médian de blocs écrits par les membres au sein de la fenêtre courante.
+/// handicap = FLOOR(LN(MAX(1;(nb_personal_blocks_in_frame + 1) / median_of_blocks_in_frame)) / LN(1.189))
+///
+/// reference dans le protocol : https://github.com/duniter/duniter/blob/master/doc/Protocol.md#br_g18---headpowzeros-and-headpowremainder
+pub fn handicap(nb_personal_blocks_in_frame: usize, median_of_blocks_in_frame: usize) -> usize {
+    (((std::cmp::max(
+        1,
+        (nb_personal_blocks_in_frame + 1) / median_of_blocks_in_frame,
+    )) as f64)
+        .ln()
+        / 1.189.ln())
+    .floor() as usize
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    //TODO: déplacer la fonction métier dans blockchain ou bc-db-writer
+
+    #[test]
+    fn test_exclusion_factor() {
+        assert_eq!(1, exclusion_factor(1, 0));
+        assert_eq!(2, exclusion_factor(15, 4));
+    }
+
+    #[test]
+    fn test_handicap() {
+        assert_eq!(13, handicap(500, 50));
+        assert_eq!(0, handicap(1, 50));
+    }
+
+    #[test]
+    fn test_compute_personal_difficulty_no_penality() {
+        assert_eq!(
+            PersonalDifficulty {
+                exclusion_factor: 1,
+                handicap: 0
+            },
+            compute_personal_difficulty(100, BlockNumber(1000), BlockNumber(1100), 2, 5)
+        );
+    }
+
+    #[test]
+    fn test_compute_personal_difficulty_double_penality() {
+        assert_eq!(
+            PersonalDifficulty {
+                exclusion_factor: 3,
+                handicap: 10
+            },
+            compute_personal_difficulty(50, BlockNumber(1000), BlockNumber(1010), 5, 1)
+        );
+    }
+}