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 9eee726e7376f5ee07dd6c0042d6235c9bc4f5ad..4497742e23d6d3ad6becad2fc29f4c9d10ac392d 100644 --- a/lib/modules-lib/bc-db-reader/src/current_frame.rs +++ b/lib/modules-lib/bc-db-reader/src/current_frame.rs @@ -21,11 +21,12 @@ use crate::current_meta_datas::get_current_blockstamp_; use crate::*; use current_meta_datas::CurrentMetaDataKey; use dubp_common_doc::BlockNumber; -use durs_dbs_tools::DbError; +//use durs_dbs_tools::DbError; use durs_wot::WotId; use entities::{MemberFrameInfo, MemberInCurrentFrame, PersonalDifficulty}; use num::Float; + /// Get current frame datas pub fn get_current_frame<DB: DbReadable>( _db: &DB, @@ -40,281 +41,7 @@ pub fn get_member_diffi<DB: DbReadable, R: DbReader>( r: &R, wot_id: WotId, ) -> Result<PersonalDifficulty, DbError> { - compute_member_diffi(db, r, wot_id) -} -/// Compute the personal difficulty of a member. -/// If the member is not in the current window, returns `pow_min`. -pub fn compute_member_diffi<DB: DbReadable, R: DbReader>( - db: &DB, - r: &R, - wot_id: WotId, -) -> Result<PersonalDifficulty, DbError> { - // si membre absent du store return personnal; - // difficulty par défaut - // sinon récupérer le résultat et continuer - let optional_member_info: Option<MemberFrameInfo> = - crate::get::get_bin_in_int_store(db, r, CURRENT_FRAME_MEMBERS, wot_id.0 as u32)?; - if let Some(member_info) = optional_member_info { - let current_block_number = get_current_blockstamp_(db, r)? - .ok_or(DbError::DBCorrupted)? - .id; - let median_frame_member = crate::get::get_required_u64_in_int_store( - db, - r, - CURRENT_METAS_DATAS, - CurrentMetaDataKey::MedianFrameMember.to_u32(), - )?; - Ok(compute_personal_difficulty( - member_info.last_personal_nb_members_in_frame.into(), - member_info.last_personal_block_number, - current_block_number, - member_info.member_in_current_frame.forged_blocks, - median_frame_member as usize, - )) - } else { - Ok(PersonalDifficulty { - exclusion_factor: 1, - handicap: 0, - }) - } -} - -/// 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, - personal_forged_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(personal_forged_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 -#[inline] -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 -/// -/// personal_forged_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;(personal_forged_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 -#[inline] -pub fn handicap(personal_forged_blocks_in_frame: usize, median_of_blocks_in_frame: usize) -> usize { - (((std::cmp::max( - 1, - (personal_forged_blocks_in_frame + 1) / median_of_blocks_in_frame, - )) as f64) - .ln() - / 1.189.ln()) - .floor() as usize + unimplemented!(); + //compute_member_diffi(db, r, wot_id) } -#[cfg(test)] -mod tests { - use super::*; - use crate::tests::*; - use dubp_common_doc::Blockstamp; - use durs_dbs_tools::kv_db::KvFileDbHandler; - - //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_default_personal_difficulty() { - assert_eq!( - PersonalDifficulty { - exclusion_factor: 1, - handicap: 0, - }, - PersonalDifficulty::default() - ); - } - - #[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) - ); - assert_eq!( - PersonalDifficulty { - exclusion_factor: 2, - handicap: 13, - }, - compute_personal_difficulty(6, BlockNumber(99), BlockNumber(100), 19, 2) - ); - assert_eq!( - PersonalDifficulty { - exclusion_factor: 1, - handicap: 6, - }, - compute_personal_difficulty(6, BlockNumber(80), BlockNumber(100), 5, 2) - ); - } - - // test avec db mockée - fn factory_member_frame_info( - last_bn: u32, - last_mf: usize, - fb: usize, - ) -> Result<Vec<u8>, DbError> { - durs_dbs_tools::to_bytes(&MemberFrameInfo { - last_personal_block_number: BlockNumber(last_bn), - last_personal_nb_members_in_frame: last_mf, - member_in_current_frame: MemberInCurrentFrame { - forged_blocks: fb, - difficulty: PersonalDifficulty::default(), - }, - }) - } - - fn put_member_frame_info_in_db( - db: &KvFileDbHandler, - w: &mut DbWriter, - wot_id: u32, - last_bn: u32, - last_mf: usize, - nbr_pbf: usize, - ) -> Result<(), DbError> { - db.get_int_store(CURRENT_FRAME_MEMBERS).put( - w.as_mut(), - wot_id, - &DbValue::Blob(&factory_member_frame_info(last_bn, last_mf, nbr_pbf)?), - )?; - Ok(()) - } - - /// cré un store CURRENT_FRAME_MEMBERS avec comme - /// |- clef les wot_id des membres de la fenêtre courante - /// |- valeurs : - /// |- le block_number du dernier block de ce membre - /// |- le nombre de membre dans la fenetre courante au dernier block de ce membre - /// |- le nombre de block de ce membre dans la fenêtre courante - fn init_mocked_db() -> Result<KvFileDbHandler, DbError> { - let db = open_tmp_db()?; - db.write(|mut w| { - put_member_frame_info_in_db(&db, &mut w, 1, 99, 6, 19)?; - put_member_frame_info_in_db(&db, &mut w, 3, 80, 6, 5)?; - put_member_frame_info_in_db(&db, &mut w, 4, 97, 6, 3)?; - put_member_frame_info_in_db(&db, &mut w, 5, 98, 6, 1)?; - put_member_frame_info_in_db(&db, &mut w, 6, 90, 6, 1)?; - put_member_frame_info_in_db(&db, &mut w, 8, 71, 6, 1)?; - - let blockstamp_bytes: Vec<u8> = Blockstamp { - id: BlockNumber(100), - ..Default::default() - } - .into(); - db.get_int_store(CURRENT_METAS_DATAS).put( - w.as_mut(), - CurrentMetaDataKey::CurrentBlockstamp.to_u32(), - &DbValue::Blob(&blockstamp_bytes), - )?; - // db.get_int_store(CURRENT_METAS_DATAS).put( - // w.as_mut(), - // CurrentMetaDataKey::CurrentFrameMembersSize.to_u32(), - // &DbValue::U64(6), - // )?; - db.get_int_store(CURRENT_METAS_DATAS).put( - w.as_mut(), - CurrentMetaDataKey::MedianFrameMember.to_u32(), - &DbValue::U64(2), - )?; - - //CurrentBlockNumber : BlockNumber - //CurrentFrameMembersSize : u32 - //MedianFrameMember : bloc_count - - Ok(w) - })?; - Ok(db) - } - - #[test] - fn test_personal_difficulty_member_not_in_frame() -> Result<(), DbError> { - let db = init_mocked_db()?; - assert_eq!( - PersonalDifficulty { - exclusion_factor: 1, - handicap: 0, - }, - db.read(|r| get_member_diffi(&db, r, WotId(0)))? - ); - Ok(()) - } - - #[test] - fn test_personal_difficulty_member_supercalculator() -> Result<(), DbError> { - let db = init_mocked_db()?; - assert_eq!( - PersonalDifficulty { - exclusion_factor: 2, - handicap: 13, - }, - db.read(|r| get_member_diffi(&db, r, WotId(1)))? - ); - Ok(()) - } - - #[test] - fn test_personal_difficulty_member_high_calculator() -> Result<(), DbError> { - let db = init_mocked_db()?; - assert_eq!( - PersonalDifficulty { - exclusion_factor: 1, - handicap: 6, - }, - db.read(|r| get_member_diffi(&db, r, WotId(3)))? - ); - Ok(()) - } -} diff --git a/lib/modules/blockchain/bc-db-writer/src/current_frame.rs b/lib/modules/blockchain/bc-db-writer/src/current_frame.rs new file mode 100644 index 0000000000000000000000000000000000000000..60c59719ea7bcb312942159523933fc2f0d68341 --- /dev/null +++ b/lib/modules/blockchain/bc-db-writer/src/current_frame.rs @@ -0,0 +1,189 @@ +// Copyright (C) 2017-2019 The AXIOM TEAM Association. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see <https://www.gnu.org/licenses/>. + +//! Dubp personal difficulty logic + +pub mod personal_diffi_computation; + +use crate::*; +use durs_wot::WotId; +use durs_bc_db_reader::current_frame::entities::{MemberFrameInfo, MemberInCurrentFrame, PersonalDifficulty}; +use durs_bc_db_reader::constants::*; +use durs_bc_db_reader::current_meta_datas::get_current_blockstamp_; +use durs_bc_db_reader::current_meta_datas::CurrentMetaDataKey; +use durs_bc_db_reader::{DbValue,DbReader}; + + +/// Compute the personal difficulty of a member. +/// If the member is not in the current window, returns `pow_min`. +pub fn compute_member_diffi<DB: DbReadable, R: DbReader>( + db: &DB, + r: &R, + wot_id: WotId, +) -> Result<PersonalDifficulty, DbError> { + // si membre absent du store return personnal; + // difficulty par défaut + // sinon récupérer le résultat et continuer + let optional_member_info: Option<MemberFrameInfo> = + durs_bc_db_reader::get::get_bin_in_int_store(db, r, CURRENT_FRAME_MEMBERS, wot_id.0 as u32)?; + if let Some(member_info) = optional_member_info { + let current_block_number = get_current_blockstamp_(db, r)? + .ok_or(DbError::DBCorrupted)? + .id; + let median_frame_member = durs_bc_db_reader::get::get_required_u64_in_int_store( + db, + r, + CURRENT_METAS_DATAS, + CurrentMetaDataKey::MedianFrameMember.to_u32(), + )?; + Ok(personal_diffi_computation::compute_personal_difficulty( + member_info.last_personal_nb_members_in_frame.into(), + member_info.last_personal_block_number, + current_block_number, + member_info.member_in_current_frame.forged_blocks, + median_frame_member as usize, + )) + } else { + Ok(PersonalDifficulty { + exclusion_factor: 1, + handicap: 0, + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::tests::*; + use dubp_common_doc::Blockstamp; + use durs_dbs_tools::kv_db::KvFileDbHandler; + + // test avec db mockée + fn factory_member_frame_info( + last_bn: u32, + last_mf: usize, + fb: usize, + ) -> Result<Vec<u8>, DbError> { + durs_dbs_tools::to_bytes(&MemberFrameInfo { + last_personal_block_number: BlockNumber(last_bn), + last_personal_nb_members_in_frame: last_mf, + member_in_current_frame: MemberInCurrentFrame { + forged_blocks: fb, + difficulty: PersonalDifficulty::default(), + }, + }) + } + + fn put_member_frame_info_in_db( + db: &KvFileDbHandler, + w: &mut DbWriter, + wot_id: u32, + last_bn: u32, + last_mf: usize, + nbr_pbf: usize, + ) -> Result<(), DbError> { + db.get_int_store(CURRENT_FRAME_MEMBERS).put( + w.as_mut(), + wot_id, + &DbValue::Blob(&factory_member_frame_info(last_bn, last_mf, nbr_pbf)?), + )?; + Ok(()) + } + + /// cré un store CURRENT_FRAME_MEMBERS avec comme + /// |- clef les wot_id des membres de la fenêtre courante + /// |- valeurs : + /// |- le block_number du dernier block de ce membre + /// |- le nombre de membre dans la fenetre courante au dernier block de ce membre + /// |- le nombre de block de ce membre dans la fenêtre courante + fn init_mocked_db() -> Result<KvFileDbHandler, DbError> { + let db = open_tmp_db()?; + db.write(|mut w| { + put_member_frame_info_in_db(&db, &mut w, 1, 99, 6, 19)?; + put_member_frame_info_in_db(&db, &mut w, 3, 80, 6, 5)?; + put_member_frame_info_in_db(&db, &mut w, 4, 97, 6, 3)?; + put_member_frame_info_in_db(&db, &mut w, 5, 98, 6, 1)?; + put_member_frame_info_in_db(&db, &mut w, 6, 90, 6, 1)?; + put_member_frame_info_in_db(&db, &mut w, 8, 71, 6, 1)?; + + let blockstamp_bytes: Vec<u8> = Blockstamp { + id: BlockNumber(100), + ..Default::default() + } + .into(); + db.get_int_store(CURRENT_METAS_DATAS).put( + w.as_mut(), + CurrentMetaDataKey::CurrentBlockstamp.to_u32(), + &DbValue::Blob(&blockstamp_bytes), + )?; + // db.get_int_store(CURRENT_METAS_DATAS).put( + // w.as_mut(), + // CurrentMetaDataKey::CurrentFrameMembersSize.to_u32(), + // &DbValue::U64(6), + // )?; + db.get_int_store(CURRENT_METAS_DATAS).put( + w.as_mut(), + CurrentMetaDataKey::MedianFrameMember.to_u32(), + &DbValue::U64(2), + )?; + + //CurrentBlockNumber : BlockNumber + //CurrentFrameMembersSize : u32 + //MedianFrameMember : bloc_count + + Ok(w) + })?; + Ok(db) + } + + #[test] + fn test_personal_difficulty_member_not_in_frame() -> Result<(), DbError> { + let db = init_mocked_db()?; + assert_eq!( + PersonalDifficulty { + exclusion_factor: 1, + handicap: 0, + }, + db.read(|r| compute_member_diffi(&db, r, WotId(0)))? + ); + Ok(()) + } + + #[test] + fn test_personal_difficulty_member_supercalculator() -> Result<(), DbError> { + let db = init_mocked_db()?; + assert_eq!( + PersonalDifficulty { + exclusion_factor: 2, + handicap: 13, + }, + db.read(|r| compute_member_diffi(&db, r, WotId(1)))? + ); + Ok(()) + } + + #[test] + fn test_personal_difficulty_member_high_calculator() -> Result<(), DbError> { + let db = init_mocked_db()?; + assert_eq!( + PersonalDifficulty { + exclusion_factor: 1, + handicap: 6, + }, + db.read(|r| compute_member_diffi(&db, r, WotId(3)))? + ); + Ok(()) + } +} diff --git a/lib/modules/blockchain/bc-db-writer/src/current_frame/personal_diffi_computation.rs b/lib/modules/blockchain/bc-db-writer/src/current_frame/personal_diffi_computation.rs new file mode 100644 index 0000000000000000000000000000000000000000..b96382dba0ae3fdbd171ae4afe039458cf2be216 --- /dev/null +++ b/lib/modules/blockchain/bc-db-writer/src/current_frame/personal_diffi_computation.rs @@ -0,0 +1,137 @@ +// Copyright (C) 2017-2019 The AXIOM TEAM Association. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see <https://www.gnu.org/licenses/>. + +//! Dubp personal difficulty computation (specific logic computation) + +use dubp_common_doc::BlockNumber; +use durs_bc_db_reader::current_frame::entities::PersonalDifficulty; + +/// 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, + personal_forged_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(personal_forged_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 +#[inline] +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 +/// +/// personal_forged_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;(personal_forged_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 +#[inline] +pub fn handicap(personal_forged_blocks_in_frame: usize, median_of_blocks_in_frame: usize) -> usize { + (((std::cmp::max( + 1, + (personal_forged_blocks_in_frame + 1) / median_of_blocks_in_frame, + )) as f64) + .ln() + / 1.189_f64.ln()) + .floor() as usize +} + +#[cfg(test)] +mod tests { + use super::*; + + #[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_default_personal_difficulty() { + assert_eq!( + PersonalDifficulty { + exclusion_factor: 1, + handicap: 0, + }, + PersonalDifficulty::default() + ); + } + + #[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) + ); + assert_eq!( + PersonalDifficulty { + exclusion_factor: 2, + handicap: 13, + }, + compute_personal_difficulty(6, BlockNumber(99), BlockNumber(100), 19, 2) + ); + assert_eq!( + PersonalDifficulty { + exclusion_factor: 1, + handicap: 6, + }, + compute_personal_difficulty(6, BlockNumber(80), BlockNumber(100), 5, 2) + ); + } +} diff --git a/lib/modules/blockchain/bc-db-writer/src/lib.rs b/lib/modules/blockchain/bc-db-writer/src/lib.rs index 282e4e5f4542d17029ddf6a65671da9c5133e807..413de1c4457d4fdc81e7f44ea616fab7e2859335 100644 --- a/lib/modules/blockchain/bc-db-writer/src/lib.rs +++ b/lib/modules/blockchain/bc-db-writer/src/lib.rs @@ -31,6 +31,7 @@ extern crate log; pub mod blocks; +pub mod current_frame; pub mod current_meta_datas; pub mod indexes; pub mod store_name; diff --git a/lib/modules/blockchain/bc-db-writer/tests/current_frame.rs b/lib/modules/blockchain/bc-db-writer/tests/current_frame.rs index a3daa223d5ec259bec769c5c9b560cf32585b3e9..4fc05fe631db6cf698ddf577368c8ed747542f89 100644 --- a/lib/modules/blockchain/bc-db-writer/tests/current_frame.rs +++ b/lib/modules/blockchain/bc-db-writer/tests/current_frame.rs @@ -17,6 +17,7 @@ use dubp_block_doc::BlockDocument; use dubp_blocks_tests_tools::mocks::gen_empty_block_v10_with_issuer_and_pow_min as gen_empty_block; use dubp_common_doc::BlockNumber; use dup_crypto_tests_tools::mocks::pubkey; +use durs_bc_db_reader::current_frame::entities::*; use durs_bc_db_reader::current_frame::*; use durs_bc_db_reader::DbReadable; use durs_bc_db_writer::blocks::insert_new_head_block;