diff --git a/Cargo.lock b/Cargo.lock index 012c031dec..be4a0a697f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1307,8 +1307,7 @@ dependencies = [ [[package]] name = "crumbles" version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8e75f60d6b7f88bcbb2468fee550a1db73c5c9d0f89526dfbd5d2aa89039636" +source = "git+https://github.com/dusk-network/piecrust?branch=issue-419-0.28.1-rc.0#0c05327738daf0b53e1b88626f1fd8501c720b49" dependencies = [ "libc", "rangemap", @@ -3693,9 +3692,8 @@ dependencies = [ [[package]] name = "piecrust" -version = "0.27.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10c5b83e833e13d1be1a5bfb7183a3edd4dbd786ec3524918c78bdc982a32c7e" +version = "0.28.0-rc.6" +source = "git+https://github.com/dusk-network/piecrust?branch=issue-419-0.28.1-rc.0#0c05327738daf0b53e1b88626f1fd8501c720b49" dependencies = [ "blake3", "bytecheck", @@ -3716,11 +3714,11 @@ dependencies = [ [[package]] name = "piecrust-uplink" version = "0.17.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e681bcea1ea7f82f8b66649da42d1fb7a23ab85f9d0acbf99fca4e560a2f1400" +source = "git+https://github.com/dusk-network/piecrust?branch=issue-419-0.28.1-rc.0#0c05327738daf0b53e1b88626f1fd8501c720b49" dependencies = [ "bytecheck", "dlmalloc", + "hex", "rkyv", ] diff --git a/Cargo.toml b/Cargo.toml index 3404fff1a5..f8d97ce97c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -61,7 +61,7 @@ jubjub-schnorr = { version = "0.5", default-features = false } kadcast = "0.7" phoenix-circuits = { version = "0.5", default-features = false } phoenix-core = { version = "0.33.1", default-features = false } -piecrust = "0.27.1" +piecrust = "0.28.0-rc.6" piecrust-uplink = "0.17.3" poseidon-merkle = "0.7" @@ -173,3 +173,7 @@ overflow-checks = true [profile.release.package.rusk-wallet] overflow-checks = true + +[patch.crates-io] +piecrust = { git = "https://github.com/dusk-network/piecrust", branch = "issue-419-0.28.1-rc.0" } +piecrust-uplink = { git = "https://github.com/dusk-network/piecrust", branch = "issue-419-0.28.1-rc.0" } \ No newline at end of file diff --git a/consensus/CHANGELOG.md b/consensus/CHANGELOG.md index 5be6ef067b..473462e379 100644 --- a/consensus/CHANGELOG.md +++ b/consensus/CHANGELOG.md @@ -7,7 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -[1.0.1] - 2025-01-23 +### Fixed + +- Fix `MismatchHeight` error message + +## [1.0.1] - 2025-01-23 ## [1.0.0] - 2025-01-16 diff --git a/consensus/src/errors.rs b/consensus/src/errors.rs index fa9c7af511..2a039c294c 100644 --- a/consensus/src/errors.rs +++ b/consensus/src/errors.rs @@ -89,7 +89,7 @@ pub enum HeaderError { UnsupportedVersion, #[error("empty block hash")] EmptyHash, - #[error("invalid block height block_height: {0}, curr_height: {0}")] + #[error("invalid block height block_height: {0}, curr_height: {1}")] MismatchHeight(u64, u64), #[error("block time is less than minimum block time")] BlockTimeLess, diff --git a/node/CHANGELOG.md b/node/CHANGELOG.md index e9d9f531e8..cb11119d9f 100644 --- a/node/CHANGELOG.md +++ b/node/CHANGELOG.md @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- Add `create_if_missing` field to `DatabaseOptions` +- Add support for `RUSK_EXT_CHAIN` env + ### Fixed - Change the way the archive synchronizes with the node Acceptor [#3359] diff --git a/node/src/chain.rs b/node/src/chain.rs index a5a4476616..d70649e1c4 100644 --- a/node/src/chain.rs +++ b/node/src/chain.rs @@ -82,14 +82,10 @@ impl ) .await?; - let state_hash = tip.inner().header().state_hash; - let provisioners_list = vm.read().await.get_provisioners(state_hash)?; - // Initialize Acceptor let acc = Acceptor::init_consensus( &self.keys_path, tip, - provisioners_list, db, network, vm, diff --git a/node/src/chain/acceptor.rs b/node/src/chain/acceptor.rs index 716339b2a3..2233c7d7b4 100644 --- a/node/src/chain/acceptor.rs +++ b/node/src/chain/acceptor.rs @@ -44,10 +44,12 @@ use crate::archive::Archive; use crate::chain::header_validation::{verify_att, verify_faults, Validator}; use crate::chain::metrics::AverageElapsedTime; use crate::database::rocksdb::{ - MD_AVG_PROPOSAL, MD_AVG_RATIFICATION, MD_AVG_VALIDATION, MD_HASH_KEY, - MD_STATE_ROOT_KEY, + Backend, MD_AVG_PROPOSAL, MD_AVG_RATIFICATION, MD_AVG_VALIDATION, + MD_HASH_KEY, MD_STATE_ROOT_KEY, +}; +use crate::database::{ + self, ConsensusStorage, DatabaseOptions, Ledger, Mempool, Metadata, DB, }; -use crate::database::{self, ConsensusStorage, Ledger, Mempool, Metadata}; use crate::{vm, Message, Network}; const CANDIDATES_DELETION_OFFSET: u64 = 10; @@ -194,7 +196,6 @@ impl Acceptor { pub async fn init_consensus( keys_path: &str, tip: BlockWithLabel, - provisioners_list: Provisioners, db: Arc>, network: Arc>, vm: Arc>, @@ -205,6 +206,8 @@ impl Acceptor { ) -> anyhow::Result { let tip_height = tip.inner().header().height; let tip_state_hash = tip.inner().header().state_hash; + let provisioners_list = + vm.read().await.get_provisioners(tip_state_hash)?; let mut provisioners_list = ContextProvisioners::new(provisioners_list); @@ -214,7 +217,7 @@ impl Acceptor { provisioners_list.apply_changes(changed_provisioners); } - let acc = Self { + let mut acc = Self { tip: RwLock::new(tip), provisioners_list: RwLock::new(provisioners_list), db: db.clone(), @@ -257,6 +260,36 @@ impl Acceptor { ); } } + let ext_db_parent_path = env::var("RUSK_EXT_CHAIN").unwrap_or_default(); + + if !ext_db_parent_path.is_empty() { + let opts = DatabaseOptions { + create_if_missing: false, + ..Default::default() + }; + let db_ext = Backend::create_or_open(ext_db_parent_path, opts); + let tip_ext = db_ext + .view(|t| { + anyhow::Ok(t.op_read(MD_HASH_KEY)?.and_then(|tip_hash| { + t.block(&tip_hash[..]) + .expect("block to be found if metadata is set") + })) + })? + .expect("Cannot find tip for ext block") + .header() + .height; + + if tip_ext > tip_height { + info!("detected ext db at height {tip_ext}. Syncing local db starting from {tip_height}" ); + + for height in tip_height + 1..=tip_ext { + let blk = db_ext + .view(|db| db.block_by_height(height))? + .expect("block to be found"); + acc.try_accept_block(&blk, false).await?; + } + } + } let tip_ts = acc.tip.read().await.inner().header().timestamp; Self::init_delay(tip_ts).await; @@ -681,6 +714,7 @@ impl Acceptor { blk: &Block, enable_consensus: bool, ) -> anyhow::Result { + info!(src = "try_accept", event = "init"); let mut events = vec![]; let mut task = self.task.write().await; @@ -701,9 +735,15 @@ impl Acceptor { ) .await?; + let header_verification_elapsed = header_verification_start.elapsed(); + info!( + src = "try_accept", + event = "header verified", + dur = header_verification_elapsed.as_millis() + ); // Elapsed time header verification histogram!("dusk_block_header_elapsed") - .record(header_verification_start.elapsed()); + .record(header_verification_elapsed); let start = std::time::Instant::now(); let mut est_elapsed_time = Duration::default(); @@ -718,12 +758,14 @@ impl Acceptor { let (contract_events, finality) = self.db.read().await.update(|db| { + info!(src = "try_accept", event = "before accept",); let (txs, verification_output, contract_events) = vm .accept( prev_header.state_hash, blk, &prev_block_voters[..], )?; + info!(src = "try_accept", event = "after accept",); for spent_tx in txs.iter() { events @@ -740,14 +782,17 @@ impl Acceptor { verification_output.event_bloom ); + info!(src = "try_accept", event = "before rolling",); let finality = self.rolling_finality::(pni, blk, db, &mut events)?; + info!(src = "try_accept", event = "after rolling",); let label = finality.0; // Store block with updated transactions with Error and // GasSpent block_size_on_disk = db.store_block(header, &txs, blk.faults(), label)?; + info!(src = "try_accept", event = "after store_block",); Ok((contract_events, finality)) })?; @@ -811,11 +856,13 @@ impl Acceptor { slashed_count += 1; } + info!(src = "try_accept", event = "before selective_update",); let selective_update = Self::selective_update( header.height, &stakes, &mut provisioners_list, ); + info!(src = "try_accept", event = "after selective_update",); if let Err(e) = selective_update { warn!("Resync provisioners due to {e:?}"); @@ -839,12 +886,18 @@ impl Acceptor { new_finals.pop_last().expect("new_finals to be not empty"); let new_final_state_root = new_final_state.state_root; // old final state roots to merge too - let old_final_state_roots = new_finals - .into_values() - .map(|finalized_info| finalized_info.state_root) - .chain([prev_final_state_root]) + + let old_final_state_roots = [prev_final_state_root] + .into_iter() + .chain( + new_finals + .into_values() + .map(|finalized_info| finalized_info.state_root), + ) .collect::>(); + info!(src = "try_accept", event = "before finalize",); vm.finalize_state(new_final_state_root, old_final_state_roots)?; + info!(src = "try_accept", event = "after finalize",); } anyhow::Ok((label, finalized)) diff --git a/node/src/database.rs b/node/src/database.rs index 08bc8e1a06..ea55523d84 100644 --- a/node/src/database.rs +++ b/node/src/database.rs @@ -237,6 +237,9 @@ pub struct DatabaseOptions { /// Enables a set of flags for collecting DB stats as log data. pub enable_debug: bool, + + /// Create the database if missing + pub create_if_missing: bool, } impl Default for DatabaseOptions { @@ -246,6 +249,7 @@ impl Default for DatabaseOptions { mempool_cf_max_write_buffer_size: 10 * 1024 * 1024, // 10 MiB blocks_cf_disable_block_cache: true, enable_debug: false, + create_if_missing: true, } } } diff --git a/node/src/database/rocksdb.rs b/node/src/database/rocksdb.rs index d8b462ac23..4bc8ec1610 100644 --- a/node/src/database/rocksdb.rs +++ b/node/src/database/rocksdb.rs @@ -153,7 +153,7 @@ impl DB for Backend { // A set of options for initializing any blocks-related CF (including // METADATA CF) let mut blocks_cf_opts = Options::default(); - blocks_cf_opts.create_if_missing(true); + blocks_cf_opts.create_if_missing(db_opts.create_if_missing); blocks_cf_opts.create_missing_column_families(true); blocks_cf_opts.set_level_compaction_dynamic_level_bytes(true); blocks_cf_opts diff --git a/rusk/src/lib/node/rusk.rs b/rusk/src/lib/node/rusk.rs index 3e06f8d4fa..669f39198e 100644 --- a/rusk/src/lib/node/rusk.rs +++ b/rusk/src/lib/node/rusk.rs @@ -321,7 +321,11 @@ impl Rusk { } } - self.set_current_commit(session.commit()?); + info!(src = "vm_accept", event = "before commit"); + let commit = session.commit()?; + info!(src = "vm_accept", event = "after commit"); + self.set_current_commit(commit); + info!(src = "vm_accept", event = "after set_current_commit"); let contract_events = events.clone(); for event in events { @@ -551,6 +555,8 @@ fn accept( Session, Vec, )> { + info!(src = "vm_accept", event = "init"); + let mut session = session; let mut block_gas_left = block_gas_limit; @@ -564,7 +570,10 @@ fn accept( for unspent_tx in txs { let tx = &unspent_tx.inner; let tx_id = unspent_tx.id(); + + info!(src = "vm_accept", event = "before execute"); let receipt = execute(&mut session, tx, execution_config)?; + info!(src = "vm_accept", event = "after execute"); event_bloom.add_events(&receipt.events); @@ -595,6 +604,7 @@ fn accept( }); } + info!(src = "vm_accept", event = "before reward"); let coinbase_events = reward_slash_and_update_root( &mut session, block_height, @@ -603,6 +613,7 @@ fn accept( slashing, voters, )?; + info!(src = "vm_accept", event = "after reward"); event_bloom.add_events(&coinbase_events); @@ -615,7 +626,9 @@ fn accept( .collect(); events.extend(coinbase_events); + info!(src = "vm_accept", event = "before calculating root"); let state_root = session.root(); + info!(src = "vm_accept", event = "after calculating root"); Ok(( spent_txs,