From 3477059108c9c9b1e1f7d9cccfec5518449a9f8c Mon Sep 17 00:00:00 2001 From: Aaron Blankstein Date: Thu, 24 Apr 2025 13:56:27 -0500 Subject: [PATCH 1/2] perf: improve next_ready_nakamoto_block * add an index for the SQLite lookup that the routine requires. this improves block processing speeds. --- CHANGELOG.md | 1 + .../src/chainstate/nakamoto/staging_blocks.rs | 16 +++++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 93f3549ed1..67d633e661 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to the versioning scheme outlined in the [README.md](RE ### Changed - Reduce the default `block_rejection_timeout_steps` configuration so that miners will retry faster when blocks fail to reach 70% approved or 30% rejected. +- Added index for `next_ready_nakamoto_block()` which improves block processing performance. ## [3.1.0.0.8] diff --git a/stackslib/src/chainstate/nakamoto/staging_blocks.rs b/stackslib/src/chainstate/nakamoto/staging_blocks.rs index 32d79ceb13..3505d41ebd 100644 --- a/stackslib/src/chainstate/nakamoto/staging_blocks.rs +++ b/stackslib/src/chainstate/nakamoto/staging_blocks.rs @@ -160,7 +160,12 @@ pub const NAKAMOTO_STAGING_DB_SCHEMA_3: &[&str] = &[ r#"UPDATE db_version SET version = 3"#, ]; -pub const NAKAMOTO_STAGING_DB_SCHEMA_LATEST: u32 = 3; +pub const NAKAMOTO_STAGING_DB_SCHEMA_4: &[&str] = &[ + r#"CREATE INDEX nakamoto_staging_blocks_by_ready_and_height ON nakamoto_staging_blocks(burn_attachable, orphaned, processed, height);"#, + r#"UPDATE db_version SET version = 4"#, +]; + +pub const NAKAMOTO_STAGING_DB_SCHEMA_LATEST: u32 = 4; pub struct NakamotoStagingBlocksConn(rusqlite::Connection); @@ -796,6 +801,15 @@ impl StacksChainState { assert_eq!(version, 3, "Nakamoto staging DB migration failure"); debug!("Migrated Nakamoto staging blocks DB to schema 3"); } + 3 => { + debug!("Migrate Nakamoto staging blocks DB to schema 3"); + for cmd in NAKAMOTO_STAGING_DB_SCHEMA_4.iter() { + conn.execute(cmd, NO_PARAMS)?; + } + let version = Self::get_nakamoto_staging_blocks_db_version(conn)?; + assert_eq!(version, 4, "Nakamoto staging DB migration failure"); + debug!("Migrated Nakamoto staging blocks DB to schema 3"); + } NAKAMOTO_STAGING_DB_SCHEMA_LATEST => { break; } From ff97989994a4df03fff6acf74aafb37530126aa1 Mon Sep 17 00:00:00 2001 From: Aaron Blankstein Date: Fri, 25 Apr 2025 11:35:33 -0500 Subject: [PATCH 2/2] perf: cache pox descendancy check in burnop processing --- stackslib/src/chainstate/burn/db/sortdb.rs | 43 ++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/stackslib/src/chainstate/burn/db/sortdb.rs b/stackslib/src/chainstate/burn/db/sortdb.rs index a8eb83eb25..680e3ef372 100644 --- a/stackslib/src/chainstate/burn/db/sortdb.rs +++ b/stackslib/src/chainstate/burn/db/sortdb.rs @@ -14,13 +14,16 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +use std::cell::RefCell; use std::cmp::Ordering; use std::collections::{HashMap, HashSet}; use std::io::{ErrorKind, Write}; use std::ops::{Deref, DerefMut}; use std::str::FromStr; +use std::sync::{Arc, LazyLock, Mutex}; use std::{cmp, fmt, fs}; +use clarity::util::lru_cache::LruCache; use clarity::vm::ast::ASTRules; use clarity::vm::costs::ExecutionCost; use clarity::vm::representations::{ClarityName, ContractName}; @@ -95,6 +98,9 @@ pub const REWARD_WINDOW_END: u64 = 144 * 90 + REWARD_WINDOW_START; pub type BlockHeaderCache = HashMap, ConsensusHash)>; +static DESCENDANCY_CACHE: LazyLock>>> = + LazyLock::new(|| Arc::new(Mutex::new(LruCache::new(2000)))); + pub enum FindIter { Found(R), Continue, @@ -1112,12 +1118,46 @@ pub trait SortitionHandle { test_debug!("No snapshot at height {}", block_at_burn_height); db_error::NotFoundError })?; + let top_sortition_id = sn.sortition_id; + + let mut cache = DESCENDANCY_CACHE + .lock() + .expect("FATAL: lock poisoned in SortitionDB"); while sn.block_height >= earliest_block_height { + match cache.get(&(sn.sortition_id, potential_ancestor.clone())) { + Ok(Some(result)) => { + if sn.sortition_id != top_sortition_id { + if let Err(_) = cache + .insert_clean((top_sortition_id, potential_ancestor.clone()), result) + { + *cache = LruCache::new(2000); + } + } + return Ok(result); + } + // not cached, don't need to do anything. + Ok(None) => {} + // cache is broken, create a new one + Err(_) => { + *cache = LruCache::new(2000); + } + } + if !sn.sortition { + if let Err(_) = + cache.insert_clean((top_sortition_id, potential_ancestor.clone()), false) + { + *cache = LruCache::new(2000); + } return Ok(false); } if &sn.winning_stacks_block_hash == potential_ancestor { + if let Err(_) = + cache.insert_clean((top_sortition_id, potential_ancestor.clone()), true) + { + *cache = LruCache::new(2000); + } return Ok(true); } @@ -1153,6 +1193,9 @@ pub trait SortitionHandle { } } } + if let Err(_) = cache.insert_clean((top_sortition_id, potential_ancestor.clone()), false) { + *cache = LruCache::new(2000); + } return Ok(false); } }