Skip to content
Snippets Groups Projects
Commit 1764f24d authored by Éloïs's avatar Éloïs
Browse files

[feat] blockchain: apply rollback

parent 9e2419c8
Branches
No related tags found
1 merge request!109Resolve "Fork resolution algorithm"
...@@ -23,7 +23,8 @@ use durs_blockchain_dal::entities::block::DALBlock; ...@@ -23,7 +23,8 @@ use durs_blockchain_dal::entities::block::DALBlock;
use durs_blockchain_dal::entities::sources::SourceAmount; use durs_blockchain_dal::entities::sources::SourceAmount;
use durs_blockchain_dal::writers::requests::*; use durs_blockchain_dal::writers::requests::*;
use durs_blockchain_dal::writers::transaction::DALTxV10; use durs_blockchain_dal::writers::transaction::DALTxV10;
use durs_blockchain_dal::{BinDB, TxV10Datas}; use durs_blockchain_dal::{BinDB, DALError, TxV10Datas};
use durs_common_tools::fatal_error;
use durs_wot::data::{NewLinkResult, RemLinkResult}; use durs_wot::data::{NewLinkResult, RemLinkResult};
use durs_wot::{NodeId, WebOfTrust}; use durs_wot::{NodeId, WebOfTrust};
use std::collections::HashMap; use std::collections::HashMap;
...@@ -41,13 +42,20 @@ pub struct ValidBlockRevertReqs( ...@@ -41,13 +42,20 @@ pub struct ValidBlockRevertReqs(
pub enum RevertValidBlockError { pub enum RevertValidBlockError {
ExcludeUnknowNodeId(), ExcludeUnknowNodeId(),
RevokeUnknowNodeId(), RevokeUnknowNodeId(),
DALError(DALError),
}
impl From<DALError> for RevertValidBlockError {
fn from(e: DALError) -> Self {
RevertValidBlockError::DALError(e)
}
} }
pub fn revert_block<W: WebOfTrust>( pub fn revert_block<W: WebOfTrust>(
dal_block: &DALBlock, dal_block: &DALBlock,
wot_index: &mut HashMap<PubKey, NodeId>, wot_index: &mut HashMap<PubKey, NodeId>,
wot_db: &BinDB<W>, wot_db: &BinDB<W>,
txs: &TxV10Datas, txs_db: &BinDB<TxV10Datas>,
) -> Result<ValidBlockRevertReqs, RevertValidBlockError> { ) -> Result<ValidBlockRevertReqs, RevertValidBlockError> {
// Revert DALBlock // Revert DALBlock
let mut block = dal_block.block.clone(); let mut block = dal_block.block.clone();
...@@ -61,7 +69,14 @@ pub fn revert_block<W: WebOfTrust>( ...@@ -61,7 +69,14 @@ pub fn revert_block<W: WebOfTrust>(
.transactions .transactions
.iter() .iter()
.map(|tx_enum| match *tx_enum { .map(|tx_enum| match *tx_enum {
TxDocOrTxHash::TxHash(ref tx_hash) => txs[tx_hash].clone(), TxDocOrTxHash::TxHash(ref tx_hash) => {
if let Ok(Some(tx)) = txs_db.read(|db| db.get(tx_hash).cloned()) {
tx
} else {
fatal_error(&format!("revert_block(): tx {} not found !", tx_hash));
panic!() // to compile
}
}
TxDocOrTxHash::TxDoc(ref _dal_tx) => panic!("Try to revert not reduce block !"), TxDocOrTxHash::TxDoc(ref _dal_tx) => panic!("Try to revert not reduce block !"),
}) })
.collect(); .collect();
......
...@@ -13,9 +13,137 @@ ...@@ -13,9 +13,137 @@
// You should have received a copy of the GNU Affero General Public License // 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/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
use crate::BlockchainModule; use crate::fork::revert_block::ValidBlockRevertReqs;
use crate::*;
use dubp_documents::Blockstamp; use dubp_documents::Blockstamp;
use durs_common_tools::fatal_error;
pub fn apply_rollback(_bc: &mut BlockchainModule, _new_bc_branch: Vec<Blockstamp>) { pub fn apply_rollback(bc: &mut BlockchainModule, new_bc_branch: Vec<Blockstamp>) {
unimplemented!() // TODO if new_bc_branch.is_empty() {
return;
}
let old_current_blockstamp = bc.current_blockstamp;
let last_common_block_number = new_bc_branch[0].id.0;
// Rollback (revert old branch)
while bc.current_blockstamp.id.0 > last_common_block_number {
if let Some(dal_block) = bc
.forks_dbs
.fork_blocks_db
.read(|db| db.get(&bc.current_blockstamp).cloned())
.unwrap_or_else(|_| {
fatal_error(&format!("revert block {} fail !", bc.current_blockstamp));
panic!()
})
{
let ValidBlockRevertReqs(bc_db_query, wot_dbs_queries, tx_dbs_queries) =
super::revert_block::revert_block(
&dal_block,
&mut bc.wot_index,
&bc.wot_databases.wot_db,
&bc.currency_databases.tx_db,
)
.unwrap_or_else(|_| {
fatal_error(&format!("revert block {} fail !", bc.current_blockstamp));
panic!()
});
// Apply db requests
bc_db_query
.apply(&bc.blocks_databases.blockchain_db, &bc.forks_dbs, None)
.expect("Fatal error : Fail to apply DBWriteRequest !");
for query in &wot_dbs_queries {
query
.apply(&bc.wot_databases, &bc.currency_params)
.expect("Fatal error : Fail to apply WotsDBsWriteRequest !");
}
for query in &tx_dbs_queries {
query
.apply(&bc.currency_databases)
.expect("Fatal error : Fail to apply CurrencyDBsWriteRequest !");
}
} else {
fatal_error("apply_rollback(): Not found current block in forks blocks DB !");
}
}
// Apply new branch
let mut new_branch_is_valid = true;
for blockstamp in &new_bc_branch {
if let Ok(Some(dal_block)) = bc
.forks_dbs
.fork_blocks_db
.read(|db| db.get(&blockstamp).cloned())
{
if let Ok(CheckAndApplyBlockReturn::ValidBlock(ValidBlockApplyReqs(
bc_db_query,
wot_dbs_queries,
tx_dbs_queries,
))) = check_and_apply_block(bc, Block::LocalBlock(dal_block.block))
{
bc.current_blockstamp = *blockstamp;
// Apply db requests
bc_db_query
.apply(&bc.blocks_databases.blockchain_db, &bc.forks_dbs, None)
.expect("Fatal error : Fail to apply DBWriteRequest !");
for query in &wot_dbs_queries {
query
.apply(&bc.wot_databases, &bc.currency_params)
.expect("Fatal error : Fail to apply WotsDBsWriteRequest !");
}
for query in &tx_dbs_queries {
query
.apply(&bc.currency_databases)
.expect("Fatal error : Fail to apply CurrencyDBsWriteRequest !");
}
} else {
new_branch_is_valid = false;
bc.invalid_forks.insert(*blockstamp);
break;
}
} else {
fatal_error(&format!(
"apply_rollback(): Fail to get block {} on new branch in forks blocks DB !",
blockstamp
));
}
}
if new_branch_is_valid {
// update main branch in fork tree
if let Err(err) = durs_blockchain_dal::writers::fork_tree::change_main_branch(
&bc.forks_dbs,
old_current_blockstamp,
bc.current_blockstamp,
) {
fatal_error(&format!("DALError: ForksDB: {:?}", err));
}
// save dbs
bc.blocks_databases.save_dbs();
bc.wot_databases.save_dbs();
bc.currency_databases.save_dbs(true, true);
// Send events stackUpValidBlock
let new_branch_blocks: Vec<BlockDocument> = new_bc_branch
.into_iter()
.map(|blockstamp| {
bc.forks_dbs
.fork_blocks_db
.read(|db| db.get(&blockstamp).cloned())
.expect("safe unwrap")
.expect("safe unwrap")
.block
})
.collect();
for block in new_branch_blocks {
events::sent::send_event(bc, &BlockchainEvent::StackUpValidBlock(Box::new(block)))
}
} else {
// reload dbs
let dbs_path = duniter_conf::get_blockchain_db_path(&bc.profile, &bc.currency);
bc.blocks_databases = BlocksV10DBs::open(Some(&dbs_path));
bc.forks_dbs = ForksDBs::open(Some(&dbs_path));
bc.wot_databases = WotsV10DBs::open(Some(&dbs_path));
bc.currency_databases = CurrencyV10DBs::open(Some(&dbs_path));
}
} }
...@@ -31,26 +31,6 @@ pub fn receive_response( ...@@ -31,26 +31,6 @@ pub fn receive_response(
if let NetworkResponse::Consensus(_, response) = *network_response.deref() { if let NetworkResponse::Consensus(_, response) = *network_response.deref() {
if let Ok(blockstamp) = response { if let Ok(blockstamp) = response {
bc.consensus = blockstamp; bc.consensus = blockstamp;
if bc.current_blockstamp.id.0 > bc.consensus.id.0 + 2 {
// Get last dal_block
let last_dal_block_id = BlockId(bc.current_blockstamp.id.0 - 1);
let last_dal_block = bc
.blocks_databases
.blockchain_db
.read(|db| db.get(&last_dal_block_id).cloned())
.expect("Fail to read blockchain DB.")
.expect("Fatal error : not foutn last dal block !");
revert_block::revert_block(
&last_dal_block,
&mut bc.wot_index,
&bc.wot_databases.wot_db,
&bc.currency_databases
.tx_db
.read(|db| db.clone())
.expect("Fail to read TxDB."),
)
.expect("Fail to revert block");
}
} }
} }
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment