diff --git a/src/spark/sparkwallet.cpp b/src/spark/sparkwallet.cpp index 00aa2b2bb8..02cbb57a67 100644 --- a/src/spark/sparkwallet.cpp +++ b/src/spark/sparkwallet.cpp @@ -110,16 +110,30 @@ CSparkWallet::CSparkWallet(const std::string& strWalletFile) { } CSparkWallet::~CSparkWallet() { + LOCK(cs_thread_pool); delete (ParallelOpThreadPool*)threadPool; threadPool = nullptr; } void CSparkWallet::FinishTasks() { + LOCK(cs_thread_pool); if (threadPool) { ((ParallelOpThreadPool*)threadPool)->Shutdown(); } } +void CSparkWallet::WaitForPendingTasks() { + LOCK(cs_thread_pool); + if (!threadPool) + return; + + auto* pool = (ParallelOpThreadPool*)threadPool; + if (pool->IsPoolShutdown()) + return; + + pool->PostTask([]() {}).wait(); +} + void CSparkWallet::resetDiversifierFromDB(CWalletDB& walletdb) { LOCK(cs_spark_wallet); walletdb.readDiversifier(lastDiversifier); diff --git a/src/spark/sparkwallet.h b/src/spark/sparkwallet.h index 6dcbb52c0f..571cebffe8 100644 --- a/src/spark/sparkwallet.h +++ b/src/spark/sparkwallet.h @@ -221,6 +221,8 @@ class CSparkWallet { // Returns the list of pairs of coins and metadata for that coin, std::list GetAvailableSparkCoins(const CCoinControl *coinControl = NULL) const; + /** Wait for all Spark wallet tasks queued before this call. */ + void WaitForPendingTasks(); void FinishTasks(); public: @@ -267,6 +269,7 @@ class CSparkWallet { const CSparkMintMeta* findMintMeta(const spark::Coin& coin) const EXCLUSIVE_LOCKS_REQUIRED(cs_spark_wallet); + CCriticalSection cs_thread_pool; void* threadPool; }; diff --git a/src/test/fixtures.cpp b/src/test/fixtures.cpp index c9117d6a4d..ace6792c3a 100644 --- a/src/test/fixtures.cpp +++ b/src/test/fixtures.cpp @@ -25,6 +25,7 @@ #include "ui_interface.h" #include "rpc/server.h" #include "rpc/register.h" +#include "spark/state.h" #include "test/testutil.h" #include "test/fixtures.h" @@ -313,5 +314,5 @@ CTransaction SparkTestingSetup::GenerateSparkSpend( SparkTestingSetup::~SparkTestingSetup() { - pwalletMain->sparkWallet->FinishTasks(); -} \ No newline at end of file + spark::CSparkState::GetState()->Reset(); +} diff --git a/src/test/spark_mintspend_test.cpp b/src/test/spark_mintspend_test.cpp index f8268de596..c6c5a5cf57 100644 --- a/src/test/spark_mintspend_test.cpp +++ b/src/test/spark_mintspend_test.cpp @@ -87,6 +87,9 @@ BOOST_AUTO_TEST_CASE(spark_mintspend_test) BOOST_CHECK_MESSAGE(mempool.size() == 0, "Mempool not cleared"); GenerateBlocks(2); + // Block and mempool updates reach the Spark wallet asynchronously. Drain + // them before deliberately rewinding the wallet and chain spend state. + pwalletMain->sparkWallet->WaitForPendingTasks(); auto tempTags = sparkState->usedLTags; sparkState->usedLTags.clear();