diff --git a/Cargo.lock b/Cargo.lock index 8181776932..79a37b3973 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7115,7 +7115,6 @@ dependencies = [ "hickory-client", "hickory-proto", "integer-encoding", - "libsqlite3-sys", "lmdb-zero", "log", "log-mdc", diff --git a/README.md b/README.md index 90d8e3a28b..ebb2fdde54 100644 --- a/README.md +++ b/README.md @@ -178,10 +178,11 @@ First you'll need to make sure you have a full development environment set up: - [Build Tools for Visual Studio 2019](https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=BuildTools&rel=16) -- Perl for OpenSSL: +- OpenSSL: - - OpenSSL is compiled and statically linked by the included [rust-openssl](https://github.com/sfackler/rust-openssl) crate - - Perl is required to compile this source on Windows, please download and install [StrawberryPerl](https://strawberryperl.com/) + - install `vcpkg` + - install static openssl `vcpkg install openssl:x64-windows-static` + - set env var: `OPENSSL_DIR=C:\vcpkg\packages\openssl_x64-windows-static`, replace `C:\vcpkg` with the root where you installed vcpkg - [Protocol Buffers](https://protobuf.dev/) - Install from https://github.com/protocolbuffers/protobuf#protobuf-compiler-installation or if you using [The Package Manager for Windows](https://chocolatey.org/), run ```choco upgrade protoc -y``` diff --git a/applications/minotari_node/src/builder.rs b/applications/minotari_node/src/builder.rs index 6b2792e2e7..2006ef5495 100644 --- a/applications/minotari_node/src/builder.rs +++ b/applications/minotari_node/src/builder.rs @@ -71,6 +71,10 @@ pub struct BaseNodeContext { } impl BaseNodeContext { + pub fn start(&self) -> Result<(), ChainStorageError> { + self.blockchain_db.start() + } + /// Waits for shutdown of the base node state machine and comms. /// This call consumes the NodeContainer instance. pub async fn wait_for_shutdown(self) { diff --git a/applications/minotari_node/src/lib.rs b/applications/minotari_node/src/lib.rs index f0f0867141..9da16bc6a8 100644 --- a/applications/minotari_node/src/lib.rs +++ b/applications/minotari_node/src/lib.rs @@ -152,6 +152,9 @@ pub async fn run_base_node_with_cli( task::spawn(run_grpc(grpc, grpc_address, auth, tls_identity, shutdown.to_signal())); } + ctx.start() + .map_err(|e| ExitError::new(ExitCode::UnknownError, &format!("Could not start database.{:?}", e)))?; + // Run, node, run! let context = CommandContext::new(&ctx, shutdown.clone()); let main_loop = CliLoop::new(context, cli.watch, cli.non_interactive_mode); diff --git a/applications/minotari_node/src/recovery.rs b/applications/minotari_node/src/recovery.rs index 86678675d8..f15c00f20c 100644 --- a/applications/minotari_node/src/recovery.rs +++ b/applications/minotari_node/src/recovery.rs @@ -118,6 +118,7 @@ pub async fn run_recovery(node_config: &BaseNodeConfig) -> Result<(), anyhow::Er difficulty_calculator, smt, )?; + db.start()?; do_recovery(db.into(), temp_db).await?; info!( @@ -154,6 +155,7 @@ async fn do_recovery( DifficultyCalculator::new(rules, Default::default()), smt, )?; + source_database.start()?; let max_height = source_database .get_chain_metadata() .map_err(|e| anyhow!("Could not get max chain height: {}", e))? diff --git a/base_layer/core/Cargo.toml b/base_layer/core/Cargo.toml index ee8fd891bc..808abd56ac 100644 --- a/base_layer/core/Cargo.toml +++ b/base_layer/core/Cargo.toml @@ -106,7 +106,6 @@ criterion = { version = "0.4.0" } tari_p2p = { path = "../../base_layer/p2p", features = ["test-mocks"] } tari_test_utils = { path = "../../infrastructure/test_utils" } # SQLite required for the integration tests -libsqlite3-sys = { version = "0.25.1", features = ["bundled"] } config = { version = "0.14.0" } env_logger = "0.7.0" tempfile = "3.1.0" diff --git a/base_layer/core/src/chain_storage/blockchain_database.rs b/base_layer/core/src/chain_storage/blockchain_database.rs index 85b51e6b25..cb9a9a4faa 100644 --- a/base_layer/core/src/chain_storage/blockchain_database.rs +++ b/base_layer/core/src/chain_storage/blockchain_database.rs @@ -230,7 +230,6 @@ where B: BlockchainBackend smt: Arc>, ) -> Result { debug!(target: LOG_TARGET, "BlockchainDatabase config: {:?}", config); - let is_empty = db.is_empty()?; let blockchain_db = BlockchainDatabase { db: Arc::new(RwLock::new(db)), validators, @@ -240,7 +239,36 @@ where B: BlockchainBackend disable_add_block_flag: Arc::new(AtomicBool::new(false)), smt, }; - let genesis_block = Arc::new(blockchain_db.consensus_manager.get_genesis_block()); + Ok(blockchain_db) + } + + pub fn start_new( + db: B, + consensus_manager: ConsensusManager, + validators: Validators, + config: BlockchainDatabaseConfig, + difficulty_calculator: DifficultyCalculator, + smt: Arc>, + ) -> Result { + let blockchain_db = BlockchainDatabase { + db: Arc::new(RwLock::new(db)), + validators, + config, + consensus_manager, + difficulty_calculator: Arc::new(difficulty_calculator), + disable_add_block_flag: Arc::new(AtomicBool::new(false)), + smt, + }; + blockchain_db.start()?; + Ok(blockchain_db) + } + + pub fn start(&self) -> Result<(), ChainStorageError> { + let (is_empty, config) = { + let db = self.db_read_access()?; + (db.is_empty()?, &self.config) + }; + let genesis_block = Arc::new(self.consensus_manager.get_genesis_block()); if is_empty { info!( target: LOG_TARGET, @@ -248,9 +276,9 @@ where B: BlockchainBackend genesis_block.block().body.to_counts_string() ); let mut txn = DbTransaction::new(); - blockchain_db.write(txn)?; + self.write(txn)?; txn = DbTransaction::new(); - blockchain_db.insert_block(genesis_block.clone())?; + self.insert_block(genesis_block.clone())?; let body = &genesis_block.block().body; let input_sum = body .inputs() @@ -268,15 +296,15 @@ where B: BlockchainBackend }); txn.set_pruned_height(0); txn.set_horizon_data(kernel_sum, total_utxo_sum); - blockchain_db.write(txn)?; - blockchain_db.store_pruning_horizon(config.pruning_horizon)?; - } else if !blockchain_db.chain_block_or_orphan_block_exists(genesis_block.accumulated_data().hash)? { + self.write(txn)?; + self.store_pruning_horizon(config.pruning_horizon)?; + } else if !self.chain_block_or_orphan_block_exists(genesis_block.accumulated_data().hash)? { // Check the genesis block in the DB. error!( target: LOG_TARGET, "Genesis block in database does not match the supplied genesis block in the code! Hash in the code \ {:?}, hash in the database {:?}", - blockchain_db.fetch_chain_header(0)?.hash(), + self.fetch_chain_header(0)?.hash(), genesis_block.accumulated_data().hash ); return Err(ChainStorageError::CorruptedDatabase( @@ -286,13 +314,13 @@ where B: BlockchainBackend )); } else { // lets load the smt into memory - let mut smt = blockchain_db.smt_write_access()?; + let mut smt = self.smt_write_access()?; warn!(target: LOG_TARGET, "Loading SMT into memory from stored db"); - *smt = blockchain_db.db_write_access()?.calculate_tip_smt()?; + *smt = self.db_write_access()?.calculate_tip_smt()?; warn!(target: LOG_TARGET, "Finished loading SMT into memory from stored db"); } if config.cleanup_orphans_at_startup { - match blockchain_db.cleanup_all_orphans() { + match self.cleanup_all_orphans() { Ok(_) => info!(target: LOG_TARGET, "Orphan database cleaned out at startup.",), Err(e) => warn!( target: LOG_TARGET, @@ -301,20 +329,20 @@ where B: BlockchainBackend } } - let pruning_horizon = blockchain_db.get_chain_metadata()?.pruning_horizon(); + let pruning_horizon = self.get_chain_metadata()?.pruning_horizon(); if config.pruning_horizon != pruning_horizon { debug!( target: LOG_TARGET, "Updating pruning horizon from {} to {}.", pruning_horizon, config.pruning_horizon, ); - blockchain_db.store_pruning_horizon(config.pruning_horizon)?; + self.store_pruning_horizon(config.pruning_horizon)?; } if !config.track_reorgs { - blockchain_db.clear_all_reorgs()?; + self.clear_all_reorgs()?; } - Ok(blockchain_db) + Ok(()) } /// Get the genesis block form the consensus manager diff --git a/base_layer/core/src/test_helpers/blockchain.rs b/base_layer/core/src/test_helpers/blockchain.rs index 91bbb03219..b145782200 100644 --- a/base_layer/core/src/test_helpers/blockchain.rs +++ b/base_layer/core/src/test_helpers/blockchain.rs @@ -126,7 +126,7 @@ pub fn create_store_with_consensus_and_validators_and_config( smt: Arc>, ) -> BlockchainDatabase { let backend = create_test_db(); - BlockchainDatabase::new( + BlockchainDatabase::start_new( backend, rules.clone(), validators, diff --git a/base_layer/core/tests/helpers/sample_blockchains.rs b/base_layer/core/tests/helpers/sample_blockchains.rs index 14badc5953..6b26b691df 100644 --- a/base_layer/core/tests/helpers/sample_blockchains.rs +++ b/base_layer/core/tests/helpers/sample_blockchains.rs @@ -258,7 +258,7 @@ pub async fn create_new_blockchain_lmdb( .unwrap(); let db = TempDatabase::new(); let smt = Arc::new(RwLock::new(OutputSmt::new())); - let db = BlockchainDatabase::new( + let db = BlockchainDatabase::start_new( db, consensus_manager.clone(), validators, diff --git a/base_layer/core/tests/tests/block_validation.rs b/base_layer/core/tests/tests/block_validation.rs index 57211c157d..53bb8a7def 100644 --- a/base_layer/core/tests/tests/block_validation.rs +++ b/base_layer/core/tests/tests/block_validation.rs @@ -364,7 +364,7 @@ async fn test_orphan_validator() { HeaderFullValidator::new(rules.clone(), difficulty_calculator.clone()), orphan_validator.clone(), ); - let db = BlockchainDatabase::new( + let db = BlockchainDatabase::start_new( backend, rules.clone(), validators, @@ -510,7 +510,7 @@ async fn test_orphan_body_validation() { HeaderFullValidator::new(rules.clone(), difficulty_calculator), BlockBodyInternalConsistencyValidator::new(rules.clone(), false, factories.clone()), ); - let db = BlockchainDatabase::new( + let db = BlockchainDatabase::start_new( backend, rules.clone(), validators, @@ -731,7 +731,7 @@ async fn test_header_validation() { HeaderFullValidator::new(rules.clone(), difficulty_calculator.clone()), BlockBodyInternalConsistencyValidator::new(rules.clone(), false, factories.clone()), ); - let db = BlockchainDatabase::new( + let db = BlockchainDatabase::start_new( backend, rules.clone(), validators, @@ -847,7 +847,7 @@ async fn test_block_sync_body_validator() { BlockBodyInternalConsistencyValidator::new(rules.clone(), false, factories.clone()), ); - let db = BlockchainDatabase::new( + let db = BlockchainDatabase::start_new( backend, rules.clone(), validators, @@ -1138,7 +1138,7 @@ async fn add_block_with_large_block() { BlockBodyInternalConsistencyValidator::new(rules.clone(), false, factories.clone()), ); - let db = BlockchainDatabase::new( + let db = BlockchainDatabase::start_new( backend, rules.clone(), validators, @@ -1199,7 +1199,7 @@ async fn add_block_with_large_many_output_block() { BlockBodyInternalConsistencyValidator::new(rules.clone(), false, factories.clone()), ); - let db = BlockchainDatabase::new( + let db = BlockchainDatabase::start_new( backend, rules.clone(), validators,