From 70c341cbf8be26676fee1d24a6d1b24d220fcec0 Mon Sep 17 00:00:00 2001 From: Peter Shugalev Date: Sun, 7 Dec 2025 16:57:38 +0100 Subject: [PATCH 1/6] Reduce memory footprint --- src/spark/state.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/spark/state.cpp b/src/spark/state.cpp index 63907d4252..36e90fcc8b 100644 --- a/src/spark/state.cpp +++ b/src/spark/state.cpp @@ -804,9 +804,12 @@ bool CheckSparkSpendTransaction( } else if (!fStatefulSigmaCheck && !gCheckProofThreadPool.IsPoolShutdown()) { // not an urgent check, put the proof into the thread pool for verification - auto future = gCheckProofThreadPool.PostTask([spend, cover_sets]() { + auto future = gCheckProofThreadPool.PostTask([spend, cover_sets]() mutable { try { - return spark::SpendTransaction::verify(*spend, cover_sets); + bool result = spark::SpendTransaction::verify(*spend, cover_sets); + spend.reset(); + cover_sets.clear(); + return result; } catch (const std::exception &) { return false; } From 53cc00c92a655fd2f7bb2f694f5bf81bd31e703c Mon Sep 17 00:00:00 2001 From: Peter Shugalev Date: Mon, 8 Dec 2025 10:32:06 +0100 Subject: [PATCH 2/6] Limit number of pending ZK proof checks --- src/liblelantus/threadpool.h | 5 +++++ src/spark/state.cpp | 31 +++++++++++++++++-------------- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/src/liblelantus/threadpool.h b/src/liblelantus/threadpool.h index 2b3b873a29..a7bd290b49 100644 --- a/src/liblelantus/threadpool.h +++ b/src/liblelantus/threadpool.h @@ -119,6 +119,11 @@ class ParallelOpThreadPool { boost::mutex::scoped_lock lock(task_queue_mutex); return shutdown; } + + std::size_t GetPendingTaskCount() { + boost::mutex::scoped_lock lock(task_queue_mutex); + return task_queue.size(); + } }; diff --git a/src/spark/state.cpp b/src/spark/state.cpp index 36e90fcc8b..b5828fc954 100644 --- a/src/spark/state.cpp +++ b/src/spark/state.cpp @@ -804,20 +804,23 @@ bool CheckSparkSpendTransaction( } else if (!fStatefulSigmaCheck && !gCheckProofThreadPool.IsPoolShutdown()) { // not an urgent check, put the proof into the thread pool for verification - auto future = gCheckProofThreadPool.PostTask([spend, cover_sets]() mutable { - try { - bool result = spark::SpendTransaction::verify(*spend, cover_sets); - spend.reset(); - cover_sets.clear(); - return result; - } catch (const std::exception &) { - return false; - } - }); - auto &checkState = gCheckedSparkSpendTransactions[hashTx]; - checkState.fChecked = false; - checkState.fResult = false; - checkState.checkInProgress = std::make_shared>(std::move(future)); + // don't post a request if there are too many tasks already + if (gCheckProofThreadPool.GetPendingTaskCount() < gCheckProofThreadPool.GetNumberOfThreads() * 2) { + auto future = gCheckProofThreadPool.PostTask([spend, cover_sets]() mutable { + try { + bool result = spark::SpendTransaction::verify(*spend, cover_sets); + spend.reset(); + cover_sets.clear(); + return result; + } catch (const std::exception &) { + return false; + } + }); + auto &checkState = gCheckedSparkSpendTransactions[hashTx]; + checkState.fChecked = false; + checkState.fResult = false; + checkState.checkInProgress = std::make_shared>(std::move(future)); + } } } while (fRecheckNeeded); From 54fbec9c6ae76399796062b6228b04946d60e167 Mon Sep 17 00:00:00 2001 From: Peter Shugalev Date: Tue, 16 Dec 2025 21:50:53 +0100 Subject: [PATCH 3/6] Limit memory consumption --- src/liblelantus/threadpool.h | 4 ++-- src/spark/state.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/liblelantus/threadpool.h b/src/liblelantus/threadpool.h index a7bd290b49..f7608c4df5 100644 --- a/src/liblelantus/threadpool.h +++ b/src/liblelantus/threadpool.h @@ -79,7 +79,7 @@ class ParallelOpThreadPool { // Post a task to the thread pool and return a future to wait for its completion boost::future PostTask(std::function task) { - boost::packaged_task packagedTask(std::move(task)); + boost::packaged_task packagedTask(task); boost::future ret = packagedTask.get_future(); boost::mutex::scoped_lock lock(task_queue_mutex); @@ -91,7 +91,7 @@ class ParallelOpThreadPool { task_queue.emplace(std::move(packagedTask)); task_queue_condition.notify_one(); - return std::move(ret); + return ret; } int GetNumberOfThreads() const { diff --git a/src/spark/state.cpp b/src/spark/state.cpp index b5828fc954..7289998dbe 100644 --- a/src/spark/state.cpp +++ b/src/spark/state.cpp @@ -805,7 +805,7 @@ bool CheckSparkSpendTransaction( else if (!fStatefulSigmaCheck && !gCheckProofThreadPool.IsPoolShutdown()) { // not an urgent check, put the proof into the thread pool for verification // don't post a request if there are too many tasks already - if (gCheckProofThreadPool.GetPendingTaskCount() < gCheckProofThreadPool.GetNumberOfThreads() * 2) { + if (gCheckProofThreadPool.GetPendingTaskCount() < (std::size_t)gCheckProofThreadPool.GetNumberOfThreads()/2) { auto future = gCheckProofThreadPool.PostTask([spend, cover_sets]() mutable { try { bool result = spark::SpendTransaction::verify(*spend, cover_sets); From b75e2d3bbfafeec193689ad212932b200821d87d Mon Sep 17 00:00:00 2001 From: Peter Shugalev Date: Wed, 17 Dec 2025 12:58:09 +0100 Subject: [PATCH 4/6] Limit number of concurrent thread in the ZK proof pool to 8 --- src/spark/state.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/spark/state.cpp b/src/spark/state.cpp index 7289998dbe..9389aca2d0 100644 --- a/src/spark/state.cpp +++ b/src/spark/state.cpp @@ -24,7 +24,7 @@ struct ProofCheckState { static std::map gCheckedSparkSpendTransactions; static CCriticalSection cs_checkedSparkSpendTransactions; -static ParallelOpThreadPool gCheckProofThreadPool(boost::thread::hardware_concurrency()); +static ParallelOpThreadPool gCheckProofThreadPool(std::max(boost::thread::hardware_concurrency(), 8u)); static CSparkState sparkState; From 844dca7b7911f31b1944850f29cb336eeaa4b77f Mon Sep 17 00:00:00 2001 From: Peter Shugalev Date: Sat, 20 Dec 2025 14:03:18 +0100 Subject: [PATCH 5/6] Reduce number of ZK proof threads to 4 --- src/liblelantus/threadpool.h | 2 +- src/spark/state.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/liblelantus/threadpool.h b/src/liblelantus/threadpool.h index f7608c4df5..1fa04369d4 100644 --- a/src/liblelantus/threadpool.h +++ b/src/liblelantus/threadpool.h @@ -49,7 +49,7 @@ class ParallelOpThreadPool { // In case of shutdown thread list will be empty and destructor will wait for this thread completion boost::thread::id currentId = boost::this_thread::get_id(); auto pThread = std::find_if(threads.begin(), threads.end(), - [=](const boost::thread &t) { return t.get_id() == currentId; }); + [currentId](const boost::thread &t) { return t.get_id() == currentId; }); if (pThread != threads.end()) { pThread->detach(); threads.erase(pThread); diff --git a/src/spark/state.cpp b/src/spark/state.cpp index 9389aca2d0..626c2dc6a7 100644 --- a/src/spark/state.cpp +++ b/src/spark/state.cpp @@ -24,7 +24,7 @@ struct ProofCheckState { static std::map gCheckedSparkSpendTransactions; static CCriticalSection cs_checkedSparkSpendTransactions; -static ParallelOpThreadPool gCheckProofThreadPool(std::max(boost::thread::hardware_concurrency(), 8u)); +static ParallelOpThreadPool gCheckProofThreadPool(std::max(boost::thread::hardware_concurrency(), 4u)); static CSparkState sparkState; From 8f13be02dfa6e1e02292648bcea82729169f1619 Mon Sep 17 00:00:00 2001 From: Peter Shugalev Date: Tue, 23 Dec 2025 08:59:04 +0100 Subject: [PATCH 6/6] Fixed bug in limiting number of threads --- src/spark/state.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/spark/state.cpp b/src/spark/state.cpp index 626c2dc6a7..3b8f537377 100644 --- a/src/spark/state.cpp +++ b/src/spark/state.cpp @@ -24,7 +24,7 @@ struct ProofCheckState { static std::map gCheckedSparkSpendTransactions; static CCriticalSection cs_checkedSparkSpendTransactions; -static ParallelOpThreadPool gCheckProofThreadPool(std::max(boost::thread::hardware_concurrency(), 4u)); +static ParallelOpThreadPool gCheckProofThreadPool(std::min(boost::thread::hardware_concurrency(), 4u)); static CSparkState sparkState;