From ad27dcf5a29d3540c15984f2a0da36859e8990fc Mon Sep 17 00:00:00 2001 From: striderDM <51991544+StriderDM@users.noreply.github.com> Date: Thu, 20 May 2021 20:20:36 +0200 Subject: [PATCH 1/5] Correct file paths Update gitignore Correct file paths in GlobalConfig to use base_path from ConfigBootstrap instead of using current directory for relative paths in the config file. --- .gitignore | 7 +- .../tari_app_utilities/src/initialization.rs | 69 ++++++++++++++++++- applications/tari_base_node/src/main.rs | 4 +- applications/tari_console_wallet/src/main.rs | 4 +- .../config/presets/tari_config_example.toml | 8 +-- common/src/dir_utils.rs | 9 ++- 6 files changed, 83 insertions(+), 18 deletions(-) diff --git a/.gitignore b/.gitignore index 30567a8efd..4e373b721b 100644 --- a/.gitignore +++ b/.gitignore @@ -33,12 +33,9 @@ report *.mdb /data/ *.sqlite3 -base_layer/wallet_ffi/build.config +/base_layer/wallet_ffi/build.config /base_layer/wallet_ffi/logs/ -base_layer/wallet_ffi/.cargo/config -/config -/stibbons -/wallet +/base_layer/wallet_ffi/.cargo/config keys.json node_modules /integration_tests/temp diff --git a/applications/tari_app_utilities/src/initialization.rs b/applications/tari_app_utilities/src/initialization.rs index dcdbd7122c..be327fcf1a 100644 --- a/applications/tari_app_utilities/src/initialization.rs +++ b/applications/tari_app_utilities/src/initialization.rs @@ -1,7 +1,7 @@ use crate::utilities::ExitCodes; use config::Config; use structopt::StructOpt; -use tari_common::{configuration::bootstrap::ApplicationType, ConfigBootstrap, GlobalConfig}; +use tari_common::{configuration::bootstrap::ApplicationType, ConfigBootstrap, DatabaseType, GlobalConfig}; pub const LOG_TARGET: &str = "tari::application"; @@ -21,7 +21,72 @@ pub fn init_configuration( bootstrap.initialize_logging()?; // Populate the configuration struct - let global_config = + let mut global_config = GlobalConfig::convert_from(cfg.clone()).map_err(|err| ExitCodes::ConfigError(err.to_string()))?; + check_file_paths(&mut global_config, &bootstrap); Ok((bootstrap, global_config, cfg)) } + +fn check_file_paths(config: &mut GlobalConfig, bootstrap: &ConfigBootstrap) { + let prepend = bootstrap.base_path.clone(); + if !config.data_dir.is_absolute() { + let mut path = prepend.clone(); + path.push(config.data_dir.clone()); + config.data_dir = path; + if let DatabaseType::LMDB(_) = config.db_type { + config.db_type = DatabaseType::LMDB(config.data_dir.join("db")); + } + } + if !config.peer_db_path.is_absolute() { + let mut path = prepend.clone(); + path.push(config.peer_db_path.clone()); + config.peer_db_path = path; + } + if !config.base_node_identity_file.is_absolute() { + let mut path = prepend.clone(); + path.push(config.base_node_identity_file.clone()); + config.base_node_identity_file = path; + } + if !config.base_node_tor_identity_file.is_absolute() { + let mut path = prepend.clone(); + path.push(config.base_node_tor_identity_file.clone()); + config.base_node_tor_identity_file = path; + } + if !config.console_wallet_db_file.is_absolute() { + let mut path = prepend.clone(); + path.push(config.console_wallet_db_file.clone()); + config.console_wallet_db_file = path; + } + if !config.console_wallet_peer_db_path.is_absolute() { + let mut path = prepend.clone(); + path.push(config.console_wallet_peer_db_path.clone()); + config.console_wallet_peer_db_path = path; + } + if !config.console_wallet_identity_file.is_absolute() { + let mut path = prepend.clone(); + path.push(config.console_wallet_identity_file.clone()); + config.console_wallet_identity_file = path; + } + if !config.console_wallet_tor_identity_file.is_absolute() { + let mut path = prepend.clone(); + path.push(config.console_wallet_tor_identity_file.clone()); + config.console_wallet_tor_identity_file = path; + } + if !config.wallet_db_file.is_absolute() { + let mut path = prepend.clone(); + path.push(config.wallet_db_file.clone()); + config.wallet_db_file = path; + } + if !config.wallet_peer_db_path.is_absolute() { + let mut path = prepend.clone(); + path.push(config.wallet_db_file.clone()); + config.wallet_db_file = path; + } + if let Some(file_path) = config.console_wallet_notify_file.clone() { + if file_path.is_absolute() { + let mut path = prepend; + path.push(file_path); + config.console_wallet_notify_file = Some(path); + } + } +} diff --git a/applications/tari_base_node/src/main.rs b/applications/tari_base_node/src/main.rs index 10db9df373..cfaf35ee69 100644 --- a/applications/tari_base_node/src/main.rs +++ b/applications/tari_base_node/src/main.rs @@ -123,10 +123,10 @@ pub const LOG_TARGET: &str = "base_node::app"; /// Application entry point fn main() { if let Err(exit_code) = main_inner() { - eprintln!("{}", exit_code); + eprintln!("{:?}", exit_code); error!( target: LOG_TARGET, - "Exiting with code ({}): {}", + "Exiting with code ({}): {:?}", exit_code.as_i32(), exit_code ); diff --git a/applications/tari_console_wallet/src/main.rs b/applications/tari_console_wallet/src/main.rs index 3b5920af33..d226cc24bd 100644 --- a/applications/tari_console_wallet/src/main.rs +++ b/applications/tari_console_wallet/src/main.rs @@ -43,10 +43,10 @@ fn main() { match main_inner() { Ok(_) => process::exit(0), Err(exit_code) => { - eprintln!("{}", exit_code); + eprintln!("{:?}", exit_code); error!( target: LOG_TARGET, - "Exiting with code ({}): {}", + "Exiting with code ({}): {:?}", exit_code.as_i32(), exit_code ); diff --git a/common/config/presets/tari_config_example.toml b/common/config/presets/tari_config_example.toml index 92afa1aa8f..4d9ab7d0dd 100644 --- a/common/config/presets/tari_config_example.toml +++ b/common/config/presets/tari_config_example.toml @@ -263,10 +263,10 @@ grpc_base_node_address = "127.0.0.1:18142" grpc_console_wallet_address = "127.0.0.1:18143" # A path to the file that stores your node identity and secret key -base_node_identity_file = "./config/base_node_id.json" +base_node_identity_file = "config/base_node_id.json" # A path to the file that stores your console wallet's node identity and secret key -console_wallet_identity_file = "./config/console_wallet_id.json" +console_wallet_identity_file = "config/console_wallet_id.json" # -------------- Transport configuration -------------- # Use TCP to connect to the Tari network. This transport can only communicate with TCP/IP addresses, so peers with @@ -304,10 +304,10 @@ tor_control_auth = "none" # or "password=xxxxxx" #socks5_auth = "none" # or "username_password=username:xxxxxxx" # A path to the file that stores the tor hidden service private key, if using the tor transport. -base_node_tor_identity_file = "./config/base_node_tor.json" +base_node_tor_identity_file = "config/base_node_tor.json" # A path to the file that stores the console wallet's tor hidden service private key, if using the tor transport. -console_wallet_tor_identity_file = "./config/cosole_wallet_tor.json" +console_wallet_tor_identity_file = "config/cosole_wallet_tor.json" ######################################################################################################################## # # diff --git a/common/src/dir_utils.rs b/common/src/dir_utils.rs index 627bf6a9e3..188265e9fb 100644 --- a/common/src/dir_utils.rs +++ b/common/src/dir_utils.rs @@ -47,9 +47,12 @@ pub fn default_subdir(path: &str, base_dir: Option<&PathBuf>) -> String { pub fn default_path(filename: &str, base_path: Option<&PathBuf>) -> PathBuf { let mut home = base_path.cloned().unwrap_or_else(|| { - let mut home = dirs_next::home_dir().unwrap_or_else(|| PathBuf::from(".")); - home.push(".tari"); - home + [ + dirs_next::home_dir().unwrap_or_else(|| PathBuf::from(".")), + PathBuf::from(".tari"), + ] + .iter() + .collect() }); home.push(filename); home From 980a6a620077d2ee43e41da2b95fd52ee5b27460 Mon Sep 17 00:00:00 2001 From: Mike the Tike Date: Tue, 13 Apr 2021 13:52:04 +0200 Subject: [PATCH 2/5] Fix potential overflow --- base_layer/mmr/src/common.rs | 37 ++++++++++++++++++++---------- base_layer/mmr/src/merkle_proof.rs | 2 +- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/base_layer/mmr/src/common.rs b/base_layer/mmr/src/common.rs index d6d57e44b5..7362869125 100644 --- a/base_layer/mmr/src/common.rs +++ b/base_layer/mmr/src/common.rs @@ -23,8 +23,9 @@ // Portions of this file were originally copyrighted (c) 2018 The Grin Developers, issued under the Apache License, // Version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0. -use crate::Hash; +use crate::{error::MerkleMountainRangeError, Hash}; use digest::Digest; +use std::convert::TryInto; const ALL_ONES: usize = std::usize::MAX; @@ -76,15 +77,27 @@ pub fn find_peaks(size: usize) -> Vec { peaks } -/// Calculates the positions of the parent and sibling of the node at the provided position. -pub fn family(pos: usize) -> (usize, usize) { +/// Calculates the positions of the (parent, sibling) of the node at the provided position. +/// Returns an error if the pos provided would result in an underflow or overflow. +pub fn family(pos: usize) -> Result<(usize, usize), MerkleMountainRangeError> { let (peak_map, height) = peak_map_height(pos); let peak = 1 << height; - if (peak_map & peak) != 0 { + + // Convert to i128 so that we don't over/underflow, and then we will cast back to usize after + let pos = pos as i128; + let peak = peak as i128; + let peak_map = peak_map as i128; + + let res = if (peak_map & peak) != 0 { (pos + 1, pos + 1 - 2 * peak) } else { (pos + 2 * peak, pos + 2 * peak - 1) - } + }; + + Ok(( + res.0.try_into().map_err(|_| MerkleMountainRangeError::OutOfRange)?, + res.1.try_into().map_err(|_| MerkleMountainRangeError::OutOfRange)?, + )) } /// For a given starting position calculate the parent and sibling positions @@ -267,13 +280,13 @@ mod test { #[test] fn families() { - assert_eq!(family(1), (2, 0)); - assert_eq!(family(0), (2, 1)); - assert_eq!(family(3), (5, 4)); - assert_eq!(family(9), (13, 12)); - assert_eq!(family(15), (17, 16)); - assert_eq!(family(6), (14, 13)); - assert_eq!(family(13), (14, 6)); + assert_eq!(family(1).unwrap(), (2, 0)); + assert_eq!(family(0).unwrap(), (2, 1)); + assert_eq!(family(3).unwrap(), (5, 4)); + assert_eq!(family(9).unwrap(), (13, 12)); + assert_eq!(family(15).unwrap(), (17, 16)); + assert_eq!(family(6).unwrap(), (14, 13)); + assert_eq!(family(13).unwrap(), (14, 6)); } #[test] diff --git a/base_layer/mmr/src/merkle_proof.rs b/base_layer/mmr/src/merkle_proof.rs index e264abc482..f43b7c150e 100644 --- a/base_layer/mmr/src/merkle_proof.rs +++ b/base_layer/mmr/src/merkle_proof.rs @@ -249,7 +249,7 @@ impl MerkleProof { } let sibling = self.path.remove(0); // FIXME Compare perf vs using a VecDeque - let (parent_pos, sibling_pos) = family(pos); + let (parent_pos, sibling_pos) = family(pos)?; if parent_pos > self.mmr_size { Err(MerkleProofError::Unexpected) } else { From 482f672d2bf691bc518dee3a5dbecf0a8dd4b422 Mon Sep 17 00:00:00 2001 From: Byron Hambly Date: Tue, 25 May 2021 13:34:36 +0200 Subject: [PATCH 3/5] [base-node] Create new orphan chain tip on chain reorg Updates the `reorganize_chain` function to insert a new orphan chain tip from the removed blocks, and a test to check this logic. --- .../src/chain_storage/blockchain_backend.rs | 16 +- .../src/chain_storage/blockchain_database.rs | 17 +- .../core/src/mempool/sync_protocol/mod.rs | 8 +- .../chain_storage_tests/chain_storage.rs | 249 ++++++++++++++++++ 4 files changed, 275 insertions(+), 15 deletions(-) diff --git a/base_layer/core/src/chain_storage/blockchain_backend.rs b/base_layer/core/src/chain_storage/blockchain_backend.rs index 01939469e7..9a7015cac3 100644 --- a/base_layer/core/src/chain_storage/blockchain_backend.rs +++ b/base_layer/core/src/chain_storage/blockchain_backend.rs @@ -22,25 +22,25 @@ use croaring::Bitmap; use tari_common_types::chain_metadata::ChainMetadata; use tari_mmr::Hash; -/// Identify behaviour for Blockchain database back ends. Implementations must support `Send` and `Sync` so that +/// Identify behaviour for Blockchain database backends. Implementations must support `Send` and `Sync` so that /// `BlockchainDatabase` can be thread-safe. The backend *must* also execute transactions atomically; i.e., every /// operation within it must succeed, or they all fail. Failure to support this contract could lead to /// synchronisation issues in your database backend. /// /// Data is passed to and from the backend via the [DbKey], [DbValue], and [DbValueKey] enums. This strategy allows -/// us to keep the reading and writing API extremely simple. Extending the types of data that the back ends can handle -/// will entail adding to those enums, and the back ends, while this trait can remain unchanged. +/// us to keep the reading and writing API extremely simple. Extending the types of data that the backends can handle +/// will entail adding to those enums, and the backends, while this trait can remain unchanged. #[allow(clippy::ptr_arg)] pub trait BlockchainBackend: Send + Sync { /// Commit the transaction given to the backend. If there is an error, the transaction must be rolled back, and /// the error condition returned. On success, every operation in the transaction will have been committed, and /// the function will return `Ok(())`. fn write(&mut self, tx: DbTransaction) -> Result<(), ChainStorageError>; - /// Fetch a value from the back end corresponding to the given key. If the value is not found, `get` must return - /// `Ok(None)`. It should only error if there is an access or integrity issue with the underlying back end. + /// Fetch a value from the backend corresponding to the given key. If the value is not found, `get` must return + /// `Ok(None)`. It should only error if there is an access or integrity issue with the underlying backend. fn fetch(&self, key: &DbKey) -> Result, ChainStorageError>; - /// Checks to see whether the given key exists in the back end. This function should only fail if there is an - /// access or integrity issue with the back end. + /// Checks to see whether the given key exists in the backend. This function should only fail if there is an + /// access or integrity issue with the backend. fn contains(&self, key: &DbKey) -> Result; /// Fetches data that is calculated and accumulated for blocks that have been @@ -129,7 +129,7 @@ pub trait BlockchainBackend: Send + Sync { /// Returns the kernel count fn kernel_count(&self) -> Result; - /// Fetches an current tip orphan by hash or returns None if the prohan is not found or is not a tip of any + /// Fetches an current tip orphan by hash or returns None if the orphan is not found or is not a tip of any /// alternate chain fn fetch_orphan_chain_tip_by_hash(&self, hash: &HashOutput) -> Result, ChainStorageError>; /// Fetch all orphans that have `hash` as a previous hash diff --git a/base_layer/core/src/chain_storage/blockchain_database.rs b/base_layer/core/src/chain_storage/blockchain_database.rs index 1481e574ec..cbd13f41d4 100644 --- a/base_layer/core/src/chain_storage/blockchain_database.rs +++ b/base_layer/core/src/chain_storage/blockchain_database.rs @@ -1265,6 +1265,8 @@ fn check_for_valid_height(db: &T, height: u64) -> Result<( Ok((tip_height, height < pruned_height)) } +/// Removes blocks from the db from current tip to specified height. +/// Returns the blocks removed, ordered from tip to height. fn rewind_to_height( db: &mut T, mut height: u64, @@ -1512,7 +1514,6 @@ fn handle_possible_reorg( let num_added_blocks = reorg_chain.len(); let removed_blocks = reorganize_chain(db, block_validator, fork_height, &reorg_chain)?; - let num_removed_blocks = removed_blocks.len(); // reorg is required when any blocks are removed or more than one are added @@ -1548,7 +1549,8 @@ fn handle_possible_reorg( } } -// Reorganize the main chain with the provided fork chain, starting at the specified height. +/// Reorganize the main chain with the provided fork chain, starting at the specified height. +/// Returns the blocks that were removed (if any), ordered from tip to fork (ie. height desc). fn reorganize_chain( backend: &mut T, block_validator: &dyn PostOrphanBodyValidation, @@ -1603,6 +1605,15 @@ fn reorganize_chain( } } + if let Some(block) = removed_blocks.first() { + // insert the new orphan chain tip + let mut txn = DbTransaction::new(); + let hash = block.hash().clone(); + debug!(target: LOG_TARGET, "Inserting new orphan chain tip: {}", hash.to_hex()); + txn.insert_orphan_chain_tip(hash); + backend.write(txn)?; + } + Ok(removed_blocks) } @@ -1632,7 +1643,7 @@ fn restore_reorged_chain( Ok(()) } -// Insert the provided block into the orphan pool and returns any new tips that were created +/// Insert the provided block into the orphan pool and returns any new tips that were created. fn insert_orphan_and_find_new_tips( db: &mut T, block: Arc, diff --git a/base_layer/core/src/mempool/sync_protocol/mod.rs b/base_layer/core/src/mempool/sync_protocol/mod.rs index 1b6c83acf7..8c550fde18 100644 --- a/base_layer/core/src/mempool/sync_protocol/mod.rs +++ b/base_layer/core/src/mempool/sync_protocol/mod.rs @@ -44,10 +44,10 @@ //! +-------+ +-----+ //! | | //! | Txn Inventory | -//! |------------------------------->| +//! |------------------------------->| //! | | //! | TransactionItem(tx_b1) | -//! |<-------------------------------| +//! |<-------------------------------| //! | ...streaming... | //! | TransactionItem(empty) | //! |<-------------------------------| @@ -55,7 +55,7 @@ //! |<-------------------------------| //! | | //! | TransactionItem(tx_a1) | -//! |------------------------------->| +//! |------------------------------->| //! | ...streaming... | //! | TransactionItem(empty) | //! |------------------------------->| @@ -147,7 +147,7 @@ where TSubstream: AsyncRead + AsyncWrite + Unpin + Send + Sync + 'static if (*status_watch.borrow()).bootstrapped { break; } - debug!( + trace!( target: LOG_TARGET, "Mempool sync still on hold, waiting for bootstrap to finish", ); diff --git a/base_layer/core/tests/chain_storage_tests/chain_storage.rs b/base_layer/core/tests/chain_storage_tests/chain_storage.rs index 1f426add56..601a8d1cf4 100644 --- a/base_layer/core/tests/chain_storage_tests/chain_storage.rs +++ b/base_layer/core/tests/chain_storage_tests/chain_storage.rs @@ -547,6 +547,255 @@ fn handle_reorg() { assert!(store.fetch_orphan(blocks[4].hash().clone()).is_ok()); // B4 } +#[test] +fn reorgs_should_update_orphan_tips() { + // Create a main chain GB -> A1 -> A2 + // Create an orphan chain GB -> B1 + // Add a block B2 that forces a reorg to B2 + // Check that A2 is in the orphan chain tips db + // Add a block A3 that forces a reorg to A3 + // Check that B2 is in the orphan chain tips db + // Add 2 blocks B3 and B4 that force a reorg to B4 + // Check that A3 is in the orphan chain tips db + // Add 2 blocks A4 and A5 that force a reorg to A5 + // Check that B4 is in the orphan chain tips db + + let network = Network::LocalNet; + let (store, blocks, outputs, consensus_manager) = create_new_blockchain(network); + + // Create "A" Chain + let mut a_store = create_store_with_consensus(consensus_manager.clone()); + let mut a_blocks = vec![blocks[0].clone()]; + let mut a_outputs = vec![outputs[0].clone()]; + + // Block A1 + let txs = vec![txn_schema!(from: vec![a_outputs[0][0].clone()], to: vec![50 * T])]; + assert!(generate_new_block_with_achieved_difficulty( + &mut a_store, + &mut a_blocks, + &mut a_outputs, + txs, + Difficulty::from(1), + &consensus_manager + ) + .is_ok()); + + store.add_block(a_blocks[1].to_arc_block()).unwrap().assert_added(); + + // Block A2 + let txs = vec![txn_schema!(from: vec![a_outputs[1][1].clone()], to: vec![30 * T])]; + assert!(generate_new_block_with_achieved_difficulty( + &mut a_store, + &mut a_blocks, + &mut a_outputs, + txs, + Difficulty::from(3), + &consensus_manager + ) + .is_ok()); + + store.add_block(a_blocks[2].to_arc_block()).unwrap().assert_added(); + let a2_hash = a_blocks[2].hash().clone(); + + // Create "B" Chain + let mut b_store = create_store_with_consensus(consensus_manager.clone()); + let mut b_blocks = vec![blocks[0].clone()]; + let mut b_outputs = vec![outputs[0].clone()]; + + // Block B1 + let txs = vec![txn_schema!(from: vec![b_outputs[0][0].clone()], to: vec![50 * T])]; + assert!(generate_new_block_with_achieved_difficulty( + &mut b_store, + &mut b_blocks, + &mut b_outputs, + txs, + Difficulty::from(2), + &consensus_manager + ) + .is_ok()); + + store.add_block(b_blocks[1].to_arc_block()).unwrap().assert_orphaned(); + let b1_hash = b_blocks[1].hash().clone(); + + // check that B1 is in orphan tips + let orphan_tip_b1 = store + .db_read_access() + .unwrap() + .fetch_orphan_chain_tip_by_hash(&b1_hash) + .unwrap(); + assert!(orphan_tip_b1.is_some()); + assert_eq!(orphan_tip_b1.unwrap().hash(), &b1_hash); + + // Block B2 + let txs = vec![txn_schema!(from: vec![b_outputs[1][0].clone()], to: vec![40 * T])]; + assert!(generate_new_block_with_achieved_difficulty( + &mut b_store, + &mut b_blocks, + &mut b_outputs, + txs, + Difficulty::from(4), + &consensus_manager + ) + .is_ok()); + + store.add_block(b_blocks[2].to_arc_block()).unwrap().assert_reorg(2, 2); + let b2_hash = b_blocks[2].hash().clone(); + + // check that A2 is now in the orphan chain tip db + let orphan_tip_a2 = store + .db_read_access() + .unwrap() + .fetch_orphan_chain_tip_by_hash(&a2_hash) + .unwrap(); + assert!(orphan_tip_a2.is_some()); + assert_eq!(orphan_tip_a2.unwrap().hash(), &a2_hash); + + // check that B1 was removed from orphan chain tips + let orphan_tip_b1 = store + .db_read_access() + .unwrap() + .fetch_orphan_chain_tip_by_hash(&b1_hash) + .unwrap(); + assert!(orphan_tip_b1.is_none()); + + // Block A3 + let txs = vec![txn_schema!(from: vec![a_outputs[2][0].clone()], to: vec![25 * T])]; + assert!(generate_new_block_with_achieved_difficulty( + &mut a_store, + &mut a_blocks, + &mut a_outputs, + txs, + Difficulty::from(5), // A chain accumulated difficulty 9 + &consensus_manager, + ) + .is_ok()); + + store.add_block(a_blocks[3].to_arc_block()).unwrap().assert_reorg(3, 2); + let a3_hash = a_blocks[3].hash().clone(); + + // check that B2 is now in the orphan chain tip db + let orphan_tip_b2 = store + .db_read_access() + .unwrap() + .fetch_orphan_chain_tip_by_hash(&b2_hash) + .unwrap(); + assert!(orphan_tip_b2.is_some()); + assert_eq!(orphan_tip_b2.unwrap().hash(), &b2_hash); + + // check that A2 was removed from orphan chain tips + let orphan_tip_a2 = store + .db_read_access() + .unwrap() + .fetch_orphan_chain_tip_by_hash(&a2_hash) + .unwrap(); + assert!(orphan_tip_a2.is_none()); + + // Block B3 + let txs = vec![txn_schema!(from: vec![b_outputs[2][0].clone()], to: vec![30 * T])]; + assert!(generate_new_block_with_achieved_difficulty( + &mut b_store, + &mut b_blocks, + &mut b_outputs, + txs, + Difficulty::from(1), // B chain accumulated difficulty 7 + &consensus_manager + ) + .is_ok()); + + store.add_block(b_blocks[3].to_arc_block()).unwrap().assert_orphaned(); + let b3_hash = b_blocks[3].hash().clone(); + + // Block B4 + let txs = vec![txn_schema!(from: vec![b_outputs[3][0].clone()], to: vec![20 * T])]; + assert!(generate_new_block_with_achieved_difficulty( + &mut b_store, + &mut b_blocks, + &mut b_outputs, + txs, + Difficulty::from(5), // B chain accumulated difficulty 12 + &consensus_manager + ) + .is_ok()); + + store.add_block(b_blocks[4].to_arc_block()).unwrap().assert_reorg(4, 3); + let b4_hash = b_blocks[4].hash().clone(); + + // check that A3 is now in the orphan chain tip db + let orphan_tip_a3 = store + .db_read_access() + .unwrap() + .fetch_orphan_chain_tip_by_hash(&a3_hash) + .unwrap(); + assert!(orphan_tip_a3.is_some()); + assert_eq!(orphan_tip_a3.unwrap().hash(), &a3_hash); + + // check that B3 was removed from orphan chain tips + let orphan_tip_b3 = store + .db_read_access() + .unwrap() + .fetch_orphan_chain_tip_by_hash(&b3_hash) + .unwrap(); + assert!(orphan_tip_b3.is_none()); + + // Block A4 + let txs = vec![txn_schema!(from: vec![a_outputs[3][0].clone()], to: vec![20 * T])]; + assert!(generate_new_block_with_achieved_difficulty( + &mut a_store, + &mut a_blocks, + &mut a_outputs, + txs, + Difficulty::from(2), // A chain accumulated difficulty 11 + &consensus_manager + ) + .is_ok()); + + store.add_block(a_blocks[4].to_arc_block()).unwrap().assert_orphaned(); + + // Block A5 + let txs = vec![txn_schema!(from: vec![a_outputs[4][0].clone()], to: vec![10 * T])]; + assert!(generate_new_block_with_achieved_difficulty( + &mut a_store, + &mut a_blocks, + &mut a_outputs, + txs, + Difficulty::from(4), // A chain accumulated difficulty 15 + &consensus_manager + ) + .is_ok()); + + store.add_block(a_blocks[5].to_arc_block()).unwrap().assert_reorg(5, 4); + + // check that B4 is now in the orphan chain tip db + let orphan_tip_b4 = store + .db_read_access() + .unwrap() + .fetch_orphan_chain_tip_by_hash(&b4_hash) + .unwrap(); + assert!(orphan_tip_b4.is_some()); + assert_eq!(orphan_tip_b4.unwrap().hash(), &b4_hash); + + // check that A3 was removed from orphan chain tips + let orphan_tip_a3 = store + .db_read_access() + .unwrap() + .fetch_orphan_chain_tip_by_hash(&a3_hash) + .unwrap(); + assert!(orphan_tip_a3.is_none()); + + // Check that B1 - B4 are orphans + assert!(store.fetch_orphan(b_blocks[1].hash().clone()).is_ok()); // B1 + assert!(store.fetch_orphan(b_blocks[2].hash().clone()).is_ok()); // B2 + assert!(store.fetch_orphan(b_blocks[3].hash().clone()).is_ok()); // B3 + assert!(store.fetch_orphan(b_blocks[4].hash().clone()).is_ok()); // B4 + + // And blocks A1 - A5 are not + assert!(store.fetch_orphan(a_blocks[1].hash().clone()).is_err()); // A1 + assert!(store.fetch_orphan(a_blocks[2].hash().clone()).is_err()); // A2 + assert!(store.fetch_orphan(a_blocks[3].hash().clone()).is_err()); // A3 + assert!(store.fetch_orphan(a_blocks[4].hash().clone()).is_err()); // A4 + assert!(store.fetch_orphan(a_blocks[5].hash().clone()).is_err()); // A5 +} + #[test] fn handle_reorg_with_no_removed_blocks() { // GB --> A1 From abfcac89be08c107f4273d39bc841c9ef43aa475 Mon Sep 17 00:00:00 2001 From: striderDM <51991544+StriderDM@users.noreply.github.com> Date: Wed, 26 May 2021 21:16:38 +0200 Subject: [PATCH 4/5] [Bugfix] Fixes path seprators Fixes problems with UNIX path seperators in Windows cargo-fmt --- .../tari_app_utilities/src/initialization.rs | 59 ++++++++----------- common/src/configuration/bootstrap.rs | 37 +++++++++--- 2 files changed, 54 insertions(+), 42 deletions(-) diff --git a/applications/tari_app_utilities/src/initialization.rs b/applications/tari_app_utilities/src/initialization.rs index be327fcf1a..ae5697fe0d 100644 --- a/applications/tari_app_utilities/src/initialization.rs +++ b/applications/tari_app_utilities/src/initialization.rs @@ -1,5 +1,6 @@ use crate::utilities::ExitCodes; use config::Config; +use std::path::PathBuf; use structopt::StructOpt; use tari_common::{configuration::bootstrap::ApplicationType, ConfigBootstrap, DatabaseType, GlobalConfig}; @@ -30,63 +31,55 @@ pub fn init_configuration( fn check_file_paths(config: &mut GlobalConfig, bootstrap: &ConfigBootstrap) { let prepend = bootstrap.base_path.clone(); if !config.data_dir.is_absolute() { - let mut path = prepend.clone(); - path.push(config.data_dir.clone()); - config.data_dir = path; + config.data_dir = concatenate_paths_normalized(prepend.clone(), config.data_dir.clone()); if let DatabaseType::LMDB(_) = config.db_type { config.db_type = DatabaseType::LMDB(config.data_dir.join("db")); } } if !config.peer_db_path.is_absolute() { - let mut path = prepend.clone(); - path.push(config.peer_db_path.clone()); - config.peer_db_path = path; + config.peer_db_path = concatenate_paths_normalized(prepend.clone(), config.peer_db_path.clone()); } if !config.base_node_identity_file.is_absolute() { - let mut path = prepend.clone(); - path.push(config.base_node_identity_file.clone()); - config.base_node_identity_file = path; + config.base_node_identity_file = + concatenate_paths_normalized(prepend.clone(), config.base_node_identity_file.clone()); } if !config.base_node_tor_identity_file.is_absolute() { - let mut path = prepend.clone(); - path.push(config.base_node_tor_identity_file.clone()); - config.base_node_tor_identity_file = path; + config.base_node_tor_identity_file = + concatenate_paths_normalized(prepend.clone(), config.base_node_tor_identity_file.clone()); } if !config.console_wallet_db_file.is_absolute() { - let mut path = prepend.clone(); - path.push(config.console_wallet_db_file.clone()); - config.console_wallet_db_file = path; + config.console_wallet_db_file = + concatenate_paths_normalized(prepend.clone(), config.console_wallet_db_file.clone()); } if !config.console_wallet_peer_db_path.is_absolute() { - let mut path = prepend.clone(); - path.push(config.console_wallet_peer_db_path.clone()); - config.console_wallet_peer_db_path = path; + config.console_wallet_peer_db_path = + concatenate_paths_normalized(prepend.clone(), config.console_wallet_peer_db_path.clone()); } if !config.console_wallet_identity_file.is_absolute() { - let mut path = prepend.clone(); - path.push(config.console_wallet_identity_file.clone()); - config.console_wallet_identity_file = path; + config.console_wallet_identity_file = + concatenate_paths_normalized(prepend.clone(), config.console_wallet_identity_file.clone()); } if !config.console_wallet_tor_identity_file.is_absolute() { - let mut path = prepend.clone(); - path.push(config.console_wallet_tor_identity_file.clone()); - config.console_wallet_tor_identity_file = path; + config.console_wallet_tor_identity_file = + concatenate_paths_normalized(prepend.clone(), config.console_wallet_tor_identity_file.clone()); } if !config.wallet_db_file.is_absolute() { - let mut path = prepend.clone(); - path.push(config.wallet_db_file.clone()); - config.wallet_db_file = path; + config.wallet_db_file = concatenate_paths_normalized(prepend.clone(), config.wallet_db_file.clone()); } if !config.wallet_peer_db_path.is_absolute() { - let mut path = prepend.clone(); - path.push(config.wallet_db_file.clone()); - config.wallet_db_file = path; + config.wallet_peer_db_path = concatenate_paths_normalized(prepend.clone(), config.wallet_peer_db_path.clone()); } if let Some(file_path) = config.console_wallet_notify_file.clone() { if file_path.is_absolute() { - let mut path = prepend; - path.push(file_path); - config.console_wallet_notify_file = Some(path); + config.console_wallet_notify_file = Some(concatenate_paths_normalized(prepend, file_path)); } } } + +fn concatenate_paths_normalized(prepend: PathBuf, extension_path: PathBuf) -> PathBuf { + let mut result = prepend; + for component in extension_path.components() { + result.push(component); + } + result +} diff --git a/common/src/configuration/bootstrap.rs b/common/src/configuration/bootstrap.rs index 2dc1c5d212..f780c5956c 100644 --- a/common/src/configuration/bootstrap.rs +++ b/common/src/configuration/bootstrap.rs @@ -140,12 +140,20 @@ pub struct ConfigBootstrap { pub miner_max_diff: Option, } +fn normalize_path(path: PathBuf) -> PathBuf { + let mut result = PathBuf::new(); + for component in path.components() { + result.push(component); + } + result +} + impl Default for ConfigBootstrap { fn default() -> Self { ConfigBootstrap { - base_path: dir_utils::default_path("", None), - config: dir_utils::default_path(DEFAULT_CONFIG, None), - log_config: dir_utils::default_path(DEFAULT_BASE_NODE_LOG_CONFIG, None), + base_path: normalize_path(dir_utils::default_path("", None)), + config: normalize_path(dir_utils::default_path(DEFAULT_CONFIG, None)), + log_config: normalize_path(dir_utils::default_path(DEFAULT_BASE_NODE_LOG_CONFIG, None)), init: false, create_id: false, daemon_mode: false, @@ -190,23 +198,34 @@ impl ConfigBootstrap { })?; if self.config.to_str() == Some("") { - self.config = dir_utils::default_path(DEFAULT_CONFIG, Some(&self.base_path)); + self.config = normalize_path(dir_utils::default_path(DEFAULT_CONFIG, Some(&self.base_path))); } if self.log_config.to_str() == Some("") { match application_type { ApplicationType::BaseNode => { - self.log_config = dir_utils::default_path(DEFAULT_BASE_NODE_LOG_CONFIG, Some(&self.base_path)); + self.log_config = normalize_path(dir_utils::default_path( + DEFAULT_BASE_NODE_LOG_CONFIG, + Some(&self.base_path), + )); }, ApplicationType::ConsoleWallet => { - self.log_config = dir_utils::default_path(DEFAULT_WALLET_LOG_CONFIG, Some(&self.base_path)); + self.log_config = normalize_path(dir_utils::default_path( + DEFAULT_WALLET_LOG_CONFIG, + Some(&self.base_path), + )); }, ApplicationType::MergeMiningProxy => { - self.log_config = - dir_utils::default_path(DEFAULT_MERGE_MINING_PROXY_LOG_CONFIG, Some(&self.base_path)) + self.log_config = normalize_path(dir_utils::default_path( + DEFAULT_MERGE_MINING_PROXY_LOG_CONFIG, + Some(&self.base_path), + )) }, ApplicationType::MiningNode => { - self.log_config = dir_utils::default_path(DEFAULT_MINING_NODE_LOG_CONFIG, Some(&self.base_path)) + self.log_config = normalize_path(dir_utils::default_path( + DEFAULT_MINING_NODE_LOG_CONFIG, + Some(&self.base_path), + )) }, } } From 89ceb418599851f555d992f55ef09f10e9b009e2 Mon Sep 17 00:00:00 2001 From: Byron Hambly Date: Fri, 28 May 2021 11:05:26 +0200 Subject: [PATCH 5/5] [base-node] update peer seeds temporarily for tari-script branch --- .../tari_base_node/src/command_handler.rs | 4 ++-- .../config/presets/tari_config_example.toml | 20 ++++++++++++------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/applications/tari_base_node/src/command_handler.rs b/applications/tari_base_node/src/command_handler.rs index 8b4a3e6562..5ff4d38725 100644 --- a/applications/tari_base_node/src/command_handler.rs +++ b/applications/tari_base_node/src/command_handler.rs @@ -141,16 +141,16 @@ impl CommandHandler { ), ); - let banned_peers = fetch_banned_peers(&peer_manager).await.unwrap(); let conns = connectivity.get_active_connections().await.unwrap(); status_line.add_field("Connections", conns.len()); + let banned_peers = fetch_banned_peers(&peer_manager).await.unwrap(); + status_line.add_field("Banned", banned_peers.len()); let num_messages = metrics .get_total_message_count_in_timespan(Duration::from_secs(60)) .await .unwrap(); status_line.add_field("Messages (last 60s)", num_messages); - status_line.add_field("Banned", banned_peers.len()); let num_active_rpc_sessions = rpc_server.get_num_active_sessions().await.unwrap(); status_line.add_field( diff --git a/common/config/presets/tari_config_example.toml b/common/config/presets/tari_config_example.toml index 66317bc9b1..d7ee0dc5f4 100644 --- a/common/config/presets/tari_config_example.toml +++ b/common/config/presets/tari_config_example.toml @@ -196,20 +196,26 @@ data_dir = "weatherwax" # new nodes can use to introduce themselves to the network. # peer_seeds = ["public_key1::address1", "public_key2::address2",... ] peer_seeds = [ + "0c3fe3c23866ed3827e1cd72aae0c9d364d860d597993104e90d9a9401e52f05::/onion3/2m2xnylrsqbaozsndkbmfisxxbwh2vgvs6oyfak2qah4snnxykrf7zad:18141", + "b6b2c8a997ba3500d44b64a3b47203d922d614c01ebd9cad5563dc59086f9938::/onion3/kxtcwaoan6wvdl4wltguo4omo2san2ge727cfoc65hrzuwixprvop5id:18141", + "4471cec2b77b1608ff26b8695281e0b4ab35bad7f882eeaab043398644094a6c::/onion3/fqmbme5qvagh2tv722nrnwwcd2ooa4aqr43mxgiozo2yq33w74bop5qd:18141", + "e427d6007cb46e8c311fc75d2daaa95898a6162ce6a29cb4ab257c2ef70bfd62::/onion3/glicssekriwwwvfm2o5sk2mari4czbd7eklv4lsdn4wmy4ljss2t7zqd:18141", + "021baaee838a6c7a21ae3ed74f1cbb27e46351b78f0e00810c1a344a9042754d::/onion3/p2z2ptouqgi3agmw62uhz2tambqfzfdtetrfw443of3jnkkiw44e2zqd:18141", + "002a5b9d129401ca250d120b126caf067f8eb7a616252e630b6974da48def71a::/onion3/cldbbow3yzgxkvz4g2apoclrkbvg3mjxdvonoaeej3tarhlzkluodeyd:18141", # t-tbn-nvir - "b60d073e2f2337fdd95a58065e1d0182cca1d36c20ed10b27bc1232bc2836a17::/onion3/ssiz76b33emcerusblo6wba3ejqsub6ihkabjilem6ygoldodf6aenid:18141", + # "b60d073e2f2337fdd95a58065e1d0182cca1d36c20ed10b27bc1232bc2836a17::/onion3/ssiz76b33emcerusblo6wba3ejqsub6ihkabjilem6ygoldodf6aenid:18141", # t-tbn-ncal - "e2cef0473117da34108dd85d4425536b8a1f317478686a6d7a0bbb5c800a747d::/onion3/3eiacmnozk7rcvrx7brhlssnpueqsjdsfbfmq63d2bk7h3vtah35tcyd:18141", + # "e2cef0473117da34108dd85d4425536b8a1f317478686a6d7a0bbb5c800a747d::/onion3/3eiacmnozk7rcvrx7brhlssnpueqsjdsfbfmq63d2bk7h3vtah35tcyd:18141", # t-tbn-oregon - "f606c82d23b2a2eda65156cef9efcaf77031d16a681fca99af7c08e98035f21d::/onion3/i7nsgt2p7tkvpnhygnvihpuaqlunbtw3zti3qvi3eur7obkjkwgla4id:18141", + # "f606c82d23b2a2eda65156cef9efcaf77031d16a681fca99af7c08e98035f21d::/onion3/i7nsgt2p7tkvpnhygnvihpuaqlunbtw3zti3qvi3eur7obkjkwgla4id:18141", # t-tbn-london - "d23cfeb05674d25c5b970b6bffefdc1e7c2c1f1f9c32fde04688d1b94c81705a::/onion3/obfjpoon2hm4uqerirhp4sf26bvq5ztokxhq274c2fg2uadrsu5drnqd:18141", + # "d23cfeb05674d25c5b970b6bffefdc1e7c2c1f1f9c32fde04688d1b94c81705a::/onion3/obfjpoon2hm4uqerirhp4sf26bvq5ztokxhq274c2fg2uadrsu5drnqd:18141", # t-tbn-stockholm - "9cedfc16708f857e070e32d9cc1939fd6a57b5945ee97fdc707aa2f034ba6507::/onion3/ryfa3iufgmvwmghyhamkjz5rfygde6kmy7e5jn5oc2n44cpbvey654ad:18141", + # "9cedfc16708f857e070e32d9cc1939fd6a57b5945ee97fdc707aa2f034ba6507::/onion3/ryfa3iufgmvwmghyhamkjz5rfygde6kmy7e5jn5oc2n44cpbvey654ad:18141", # t-tbn-seoul - "50ee725e2c6ca8282ab62bb7aef52a9c4df283ec99e00497a358dbaf4112ff0c::/onion3/yrzdnyayg2jqym7rmeoc3lwixylasokqwkrtqyvutobllz27jdznuoyd:18141", + # "50ee725e2c6ca8282ab62bb7aef52a9c4df283ec99e00497a358dbaf4112ff0c::/onion3/yrzdnyayg2jqym7rmeoc3lwixylasokqwkrtqyvutobllz27jdznuoyd:18141", # t-tbn-sydney - "f0515584db420849a6c149517e4b326616d2d0b346f6f887adbf2c3937a87b5a::/onion3/n4kq54sjyghe4mvopk5gtmep5etblrdpqcx65o44stdb33od3tksmfqd:18141", + # "f0515584db420849a6c149517e4b326616d2d0b346f6f887adbf2c3937a87b5a::/onion3/n4kq54sjyghe4mvopk5gtmep5etblrdpqcx65o44stdb33od3tksmfqd:18141", # backup-node #"4a0c44d9132a8275d5ef8a969fb5d6085026b2d440350a3b238dfbbd1c068649::/onion3/fych32gn6yrvscbytm252woulv7o66q3pttirdmt7jlh7uyulcoikfad:18141" ]