diff --git a/build_msvc/libtest_util/libtest_util.vcxproj.in b/build_msvc/libtest_util/libtest_util.vcxproj.in
index b5e844010e9..64cfa82dccd 100644
--- a/build_msvc/libtest_util/libtest_util.vcxproj.in
+++ b/build_msvc/libtest_util/libtest_util.vcxproj.in
@@ -8,6 +8,7 @@
StaticLibrary
+
@SOURCE_FILES@
diff --git a/src/wallet/test/util.cpp b/src/wallet/test/util.cpp
index b7bf312edf1..7d0a814ed44 100644
--- a/src/wallet/test/util.cpp
+++ b/src/wallet/test/util.cpp
@@ -7,6 +7,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -79,4 +80,93 @@ CTxDestination getNewDestination(CWallet& w, OutputType output_type)
return *Assert(w.GetNewDestination(output_type, ""));
}
+DatabaseCursor::Status MockableCursor::Next(DataStream& key, DataStream& value)
+{
+ if (!m_pass) {
+ return Status::FAIL;
+ }
+ if (m_cursor == m_cursor_end) {
+ return Status::DONE;
+ }
+ const auto& [key_data, value_data] = *m_cursor;
+ key.write(key_data);
+ value.write(value_data);
+ m_cursor++;
+ return Status::MORE;
+}
+
+bool MockableBatch::ReadKey(DataStream&& key, DataStream& value)
+{
+ if (!m_pass) {
+ return false;
+ }
+ SerializeData key_data{key.begin(), key.end()};
+ const auto& it = m_records.find(key_data);
+ if (it == m_records.end()) {
+ return false;
+ }
+ value.write(it->second);
+ return true;
+}
+
+bool MockableBatch::WriteKey(DataStream&& key, DataStream&& value, bool overwrite)
+{
+ if (!m_pass) {
+ return false;
+ }
+ SerializeData key_data{key.begin(), key.end()};
+ SerializeData value_data{value.begin(), value.end()};
+ auto [it, inserted] = m_records.emplace(key_data, value_data);
+ if (!inserted && overwrite) { // Overwrite if requested
+ it->second = value_data;
+ inserted = true;
+ }
+ return inserted;
+}
+
+bool MockableBatch::EraseKey(DataStream&& key)
+{
+ if (!m_pass) {
+ return false;
+ }
+ SerializeData key_data{key.begin(), key.end()};
+ m_records.erase(key_data);
+ return true;
+}
+
+bool MockableBatch::HasKey(DataStream&& key)
+{
+ if (!m_pass) {
+ return false;
+ }
+ SerializeData key_data{key.begin(), key.end()};
+ return m_records.count(key_data) > 0;
+}
+
+bool MockableBatch::ErasePrefix(Span prefix)
+{
+ if (!m_pass) {
+ return false;
+ }
+ auto it = m_records.begin();
+ while (it != m_records.end()) {
+ auto& key = it->first;
+ if (key.size() < prefix.size() || std::search(key.begin(), key.end(), prefix.begin(), prefix.end()) != key.begin()) {
+ it++;
+ continue;
+ }
+ it = m_records.erase(it);
+ }
+ return true;
+}
+
+std::unique_ptr CreateMockableWalletDatabase(std::map records)
+{
+ return std::make_unique(records);
+}
+
+MockableDatabase& GetMockableDatabase(CWallet& wallet)
+{
+ return dynamic_cast(wallet.GetDatabase());
+}
} // namespace wallet
diff --git a/src/wallet/test/util.h b/src/wallet/test/util.h
index d726517e211..92405107cf2 100644
--- a/src/wallet/test/util.h
+++ b/src/wallet/test/util.h
@@ -6,6 +6,8 @@
#define BITCOIN_WALLET_TEST_UTIL_H
#include