From 7ee4edc7ab976a137b1b2556000eddee229f4645 Mon Sep 17 00:00:00 2001 From: SW van Heerden Date: Wed, 28 Apr 2021 09:31:30 +0200 Subject: [PATCH] remove add inputs add further checks redo audit --- .../horizon_state_synchronization.rs | 2 ++ .../base_node/sync/block_sync/synchronizer.rs | 12 ++------ base_layer/core/src/chain_storage/async_db.rs | 11 +++++-- .../src/chain_storage/blockchain_database.rs | 4 ++- .../core/src/chain_storage/db_transaction.rs | 21 ++++++------- .../core/src/chain_storage/lmdb_db/lmdb_db.rs | 30 ++++++++++++++++++- base_layer/core/tests/node_comms_interface.rs | 5 ---- 7 files changed, 56 insertions(+), 29 deletions(-) diff --git a/base_layer/core/src/base_node/state_machine_service/states/horizon_state_sync/horizon_state_synchronization.rs b/base_layer/core/src/base_node/state_machine_service/states/horizon_state_sync/horizon_state_synchronization.rs index 6a2e7f5a97f..e3577be928d 100644 --- a/base_layer/core/src/base_node/state_machine_service/states/horizon_state_sync/horizon_state_synchronization.rs +++ b/base_layer/core/src/base_node/state_machine_service/states/horizon_state_sync/horizon_state_synchronization.rs @@ -510,6 +510,7 @@ impl<'a, B: BlockchainBackend + 'static> HorizonStateSynchronization<'a, B> { let mut prev_mmr = 0; let mut prev_kernel_mmr = 0; + let prev_chain_meta = self.shared.db.get_chain_metadata().await?; for h in 0..=header.height() { let curr_header = self.db().fetch_chain_header(h).await?; @@ -594,6 +595,7 @@ impl<'a, B: BlockchainBackend + 'static> HorizonStateSynchronization<'a, B> { header.height(), header.hash().clone(), header.accumulated_data.total_accumulated_difficulty, + prev_chain_meta.best_block().clone(), ) .set_pruned_height(header.height(), pruned_kernel_sum, pruned_utxo_sum) .commit() diff --git a/base_layer/core/src/base_node/sync/block_sync/synchronizer.rs b/base_layer/core/src/base_node/sync/block_sync/synchronizer.rs index 8d51cdec306..c700b4d3350 100644 --- a/base_layer/core/src/base_node/sync/block_sync/synchronizer.rs +++ b/base_layer/core/src/base_node/sync/block_sync/synchronizer.rs @@ -169,6 +169,7 @@ impl BlockSynchronizer { .ok_or_else(|| { BlockSyncError::ReceivedInvalidBlockBody("Peer sent hash for block header we do not have".into()) })?; + let prev_chain_meta = self.db.get_chain_metadata().await?; let header_hash = header.hash().clone(); @@ -219,6 +220,7 @@ impl BlockSynchronizer { block.height(), header_hash, block.accumulated_data.total_accumulated_difficulty, + prev_chain_meta.best_block().clone(), ) .commit() .await?; @@ -242,16 +244,6 @@ impl BlockSynchronizer { } if let Some(block) = current_block { - // Update metadata to last tip header - let header = &block.block.header; - let height = header.height; - let best_block = header.hash(); - let accumulated_difficulty = block.accumulated_data.total_accumulated_difficulty; - self.db - .write_transaction() - .set_best_block(height, best_block.to_vec(), accumulated_difficulty) - .commit() - .await?; self.hooks.call_on_complete_hooks(block); } diff --git a/base_layer/core/src/chain_storage/async_db.rs b/base_layer/core/src/chain_storage/async_db.rs index e8dcd31bdfd..5a0f6dc2bea 100644 --- a/base_layer/core/src/chain_storage/async_db.rs +++ b/base_layer/core/src/chain_storage/async_db.rs @@ -253,8 +253,15 @@ impl<'a, B: BlockchainBackend + 'static> AsyncDbTransaction<'a, B> { } } - pub fn set_best_block(&mut self, height: u64, hash: HashOutput, accumulated_data: u128) -> &mut Self { - self.transaction.set_best_block(height, hash, accumulated_data); + pub fn set_best_block( + &mut self, + height: u64, + hash: HashOutput, + accumulated_data: u128, + from: HashOutput, + ) -> &mut Self + { + self.transaction.set_best_block(height, hash, accumulated_data, from); self } diff --git a/base_layer/core/src/chain_storage/blockchain_database.rs b/base_layer/core/src/chain_storage/blockchain_database.rs index d81e498d05e..c4faffe9f8b 100644 --- a/base_layer/core/src/chain_storage/blockchain_database.rs +++ b/base_layer/core/src/chain_storage/blockchain_database.rs @@ -1183,9 +1183,10 @@ fn insert_block(txn: &mut DbTransaction, block: Arc) -> Result<(), C let height = block.height(); let accumulated_difficulty = block.accumulated_data.total_accumulated_difficulty; + let prev_hash = block.block.header.prev_hash.clone(); txn.insert_header(block.block.header.clone(), block.accumulated_data.clone()) .insert_block_body(block) - .set_best_block(height, block_hash, accumulated_difficulty); + .set_best_block(height, block_hash, accumulated_difficulty, prev_hash); Ok(()) } @@ -1540,6 +1541,7 @@ fn rewind_to_height( last_header.height, header_accumulated_data.hash.clone(), header_accumulated_data.total_accumulated_difficulty, + metadata.best_block().clone(), ); db.write(txn)?; diff --git a/base_layer/core/src/chain_storage/db_transaction.rs b/base_layer/core/src/chain_storage/db_transaction.rs index 23936442eb0..e10cbd84a65 100644 --- a/base_layer/core/src/chain_storage/db_transaction.rs +++ b/base_layer/core/src/chain_storage/db_transaction.rs @@ -141,15 +141,6 @@ impl DbTransaction { self } - pub fn insert_input(&mut self, input: TransactionInput, header_hash: HashOutput, mmr_leaf_index: u32) -> &mut Self { - self.operations.push(WriteOperation::InsertInput { - header_hash, - input: Box::new(input), - mmr_position: mmr_leaf_index, - }); - self - } - pub fn update_pruned_hash_set( &mut self, mmr_tree: MmrTree, @@ -211,11 +202,19 @@ impl DbTransaction { self } - pub fn set_best_block(&mut self, height: u64, hash: HashOutput, accumulated_difficulty: u128) -> &mut Self { + pub fn set_best_block( + &mut self, + height: u64, + hash: HashOutput, + accumulated_difficulty: u128, + from: HashOutput, + ) -> &mut Self + { self.operations.push(WriteOperation::SetBestBlock { height, hash, accumulated_difficulty, + from, }); self } @@ -310,6 +309,7 @@ pub enum WriteOperation { height: u64, hash: HashOutput, accumulated_difficulty: u128, + from: HashOutput, }, SetPruningHorizonConfig(u64), SetPrunedHeight { @@ -415,6 +415,7 @@ impl fmt::Display for WriteOperation { height, hash, accumulated_difficulty, + from: _, } => write!( f, "Update best block to height:{} ({}) with difficulty: {}", diff --git a/base_layer/core/src/chain_storage/lmdb_db/lmdb_db.rs b/base_layer/core/src/chain_storage/lmdb_db/lmdb_db.rs index 72ee5a961c1..51f56edabf9 100644 --- a/base_layer/core/src/chain_storage/lmdb_db/lmdb_db.rs +++ b/base_layer/core/src/chain_storage/lmdb_db/lmdb_db.rs @@ -218,7 +218,13 @@ impl LMDBDatabase { lmdb_delete(&write_txn, &self.orphan_chain_tips_db, &hash)?; }, InsertOrphanChainTip(hash) => { - lmdb_replace(&write_txn, &self.orphan_chain_tips_db, &hash, &hash)?; + lmdb_insert( + &write_txn, + &self.orphan_chain_tips_db, + &hash, + &hash, + "orphan_chain_tips_db", + )?; }, DeleteBlock(hash) => { self.delete_block_body(&write_txn, hash)?; @@ -261,7 +267,29 @@ impl LMDBDatabase { height, hash, accumulated_difficulty, + from, } => { + // for security we check that the best block does exist, and we check the previous value + // we dont want to check this if the prev block has never been set, this means a empty hash of 32 + // bytes. + if height > 0 { + let prev = fetch_best_block(&write_txn, &self.metadata_db)?; + if from != prev { + return Err(ChainStorageError::InvalidOperation(format!( + "There was a change in best_block, the best block is suppose to be: ({}), but it \ + currently is: ({})", + from.to_hex(), + prev.to_hex(), + ))); + }; + } + if !lmdb_exists(&write_txn, &self.block_hashes_db, hash.as_slice())? { + // we dont care about the header or the height, we just want to know its there. + return Err(ChainStorageError::InvalidOperation(format!( + "There is no Blockheader hash ({}) in db", + from.to_hex(), + ))); + }; self.set_metadata(&write_txn, MetadataKey::ChainHeight, MetadataValue::ChainHeight(height))?; self.set_metadata(&write_txn, MetadataKey::BestBlock, MetadataValue::BestBlock(hash))?; self.set_metadata( diff --git a/base_layer/core/tests/node_comms_interface.rs b/base_layer/core/tests/node_comms_interface.rs index 13b5e702de0..0cb53fc1447 100644 --- a/base_layer/core/tests/node_comms_interface.rs +++ b/base_layer/core/tests/node_comms_interface.rs @@ -303,17 +303,12 @@ async fn inbound_fetch_txos() { txn.insert_utxo(utxo.clone(), header_hash.clone(), 6000); txn.insert_utxo(stxo.clone(), header_hash.clone(), 6001); assert!(store.commit(txn).is_ok()); - let mut txn = DbTransaction::new(); - txn.insert_input(stxo.clone().into(), header_hash.clone(), 1); - assert!(store.commit(txn).is_ok()); - if let Ok(NodeCommsResponse::TransactionOutputs(received_txos)) = inbound_nch .handle_request(NodeCommsRequest::FetchMatchingTxos(vec![utxo_hash, stxo_hash])) .await { assert_eq!(received_txos.len(), 2); assert_eq!(received_txos[0], utxo); - assert_eq!(received_txos[1], stxo); } else { panic!(); }