diff --git a/CHANGELOG.md b/CHANGELOG.md index f7ab38e17c..62f5d3c76d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,7 @@ - [BREAKING] Renamed `SubmitProvenBatch` RPC endpoint to `SubmitProvenTxBatch` ([#2094](https://github.com/0xMiden/node/pull/2094)). - Fixed block producer mempool panic when selecting transactions that depend on notes created by pruned committed transactions ([#2097](https://github.com/0xMiden/node/pull/2097)). - Implemented filtering based on the network account note script root allowlist in ntx-builder ([#2042](https://github.com/0xMiden/node/issues/2042)). +- Fixed RocksDB SMT subtree helpers to return storage errors for unsupported depths instead of panicking ([#1730](https://github.com/0xMiden/node/issues/1730)). - [BREAKING] Renamed `ExplorerStatusDetails` fields in the network monitor's `/status` payload from `number_of_*` to `total_*` (`total_transactions`, `total_nullifiers`, `total_notes`, `total_account_updates`). The values now represent network-wide cumulative totals from the explorer's `overviewStats` query instead of last-block counts. - [BREAKING] Removed `--wallet-filepath` / `--counter-filepath` flags and the `MIDEN_MONITOR_WALLET_FILEPATH` / `MIDEN_MONITOR_COUNTER_FILEPATH` env vars from the network monitor. The monitor now keeps wallet and counter accounts fully in memory and regenerates them on every startup; the dashboard's counter value resets to zero on restart. diff --git a/crates/large-smt-backend-rocksdb/src/rocksdb.rs b/crates/large-smt-backend-rocksdb/src/rocksdb.rs index 1310ae6dff..94f21842fc 100644 --- a/crates/large-smt-backend-rocksdb/src/rocksdb.rs +++ b/crates/large-smt-backend-rocksdb/src/rocksdb.rs @@ -306,16 +306,16 @@ impl RocksDbStorage { /// Converts a `NodeIndex` (for a subtree root) into a `KeyBytes` for use as a `RocksDB` key. /// The `KeyBytes` is a wrapper around a 8-byte value with a variable-length prefix. #[inline(always)] - fn subtree_db_key(index: NodeIndex) -> KeyBytes { + fn subtree_db_key(index: NodeIndex) -> Result { let keep = match index.depth() { 24 => 3, 32 => 4, 40 => 5, 48 => 6, 56 => 7, - d => panic!("unsupported depth {d}"), + d => return Err(StorageError::Unsupported(format!("unsupported subtree depth {d}"))), }; - KeyBytes::new(index.position(), keep) + Ok(KeyBytes::new(index.position(), keep)) } /// Retrieves a handle to a `RocksDB` column family by its name. @@ -331,9 +331,9 @@ impl RocksDbStorage { /* helper: CF handle from NodeIndex ------------------------------------- */ #[inline(always)] - fn subtree_cf(&self, index: NodeIndex) -> &rocksdb::ColumnFamily { - let name = cf_for_depth(index.depth()); - self.cf_handle(name).expect("CF handle missing") + fn subtree_cf(&self, index: NodeIndex) -> Result<&rocksdb::ColumnFamily, StorageError> { + let name = cf_for_depth(index.depth())?; + self.cf_handle(name) } } @@ -624,8 +624,8 @@ impl SmtStorage for RocksDbStorage { /// - `Ok(...)` if all fetches succeed. /// - `Err(StorageError)` if any RocksDB access or deserialization fails. fn get_subtree(&self, index: NodeIndex) -> Result, StorageError> { - let cf = self.subtree_cf(index); - let key = Self::subtree_db_key(index); + let cf = self.subtree_cf(index)?; + let key = Self::subtree_db_key(index)?; match self.db.get_cf(cf, key).map_err(map_rocksdb_err)? { Some(bytes) => { let subtree = Subtree::from_vec(index, &bytes)?; @@ -680,9 +680,10 @@ impl SmtStorage for RocksDbStorage { .map( |(bucket_index, bucket)| -> Result)>, StorageError> { let depth = SUBTREE_DEPTHS[bucket_index]; - let cf = self.cf_handle(cf_for_depth(depth))?; - let keys: Vec<_> = + let cf = self.cf_handle(cf_for_depth(depth)?)?; + let keys: Result, _> = bucket.iter().map(|(_, idx)| Self::subtree_db_key(*idx)).collect(); + let keys = keys?; let db_results = self.db.multi_get_cf(keys.iter().map(|k| (cf, k.as_ref()))); @@ -726,10 +727,10 @@ impl SmtStorage for RocksDbStorage { /// - Returns `StorageError` if column family lookup, serialization, or the write operation /// fails. fn set_subtree(&mut self, subtree: &Subtree) -> Result<(), StorageError> { - let subtrees_cf = self.subtree_cf(subtree.root_index()); + let subtrees_cf = self.subtree_cf(subtree.root_index())?; let mut batch = WriteBatch::default(); - let key = Self::subtree_db_key(subtree.root_index()); + let key = Self::subtree_db_key(subtree.root_index())?; let value = subtree.to_vec(); batch.put_cf(subtrees_cf, key, value); @@ -768,8 +769,8 @@ impl SmtStorage for RocksDbStorage { let mut batch = WriteBatch::default(); for subtree in subtrees { - let subtrees_cf = self.subtree_cf(subtree.root_index()); - let key = Self::subtree_db_key(subtree.root_index()); + let subtrees_cf = self.subtree_cf(subtree.root_index())?; + let key = Self::subtree_db_key(subtree.root_index())?; let value = subtree.to_vec(); batch.put_cf(subtrees_cf, key, value); @@ -791,10 +792,10 @@ impl SmtStorage for RocksDbStorage { /// - `StorageError::Backend`: If the subtrees column family is missing or a RocksDB error /// occurs. fn remove_subtree(&mut self, index: NodeIndex) -> Result<(), StorageError> { - let subtrees_cf = self.subtree_cf(index); + let subtrees_cf = self.subtree_cf(index)?; let mut batch = WriteBatch::default(); - let key = Self::subtree_db_key(index); + let key = Self::subtree_db_key(index)?; batch.delete_cf(subtrees_cf, key); // Also remove level 24 hash cache if this is a level 24 subtree @@ -958,8 +959,8 @@ impl SmtStorage for RocksDbStorage { }, }; - let key = Self::subtree_db_key(index); - let subtrees_cf = self.subtree_cf(index); + let key = Self::subtree_db_key(index)?; + let subtrees_cf = self.subtree_cf(index)?; Ok((subtrees_cf, key, maybe_bytes, depth24_op)) }) @@ -1586,13 +1587,13 @@ fn subtree_root_from_key_bytes(key_bytes: &[u8], depth: u8) -> Result &'static str { +fn cf_for_depth(depth: u8) -> Result<&'static str, StorageError> { match depth { - 24 => SUBTREE_24_CF, - 32 => SUBTREE_32_CF, - 40 => SUBTREE_40_CF, - 48 => SUBTREE_48_CF, - 56 => SUBTREE_56_CF, - _ => panic!("unsupported subtree depth: {depth}"), + 24 => Ok(SUBTREE_24_CF), + 32 => Ok(SUBTREE_32_CF), + 40 => Ok(SUBTREE_40_CF), + 48 => Ok(SUBTREE_48_CF), + 56 => Ok(SUBTREE_56_CF), + _ => Err(StorageError::Unsupported(format!("unsupported subtree depth {depth}"))), } }