aboutsummaryrefslogtreecommitdiff
path: root/src/wallet/bdb.cpp
diff options
context:
space:
mode:
authorAndrew Chow <achow101-github@achow101.com>2022-04-11 17:11:37 -0400
committerAndrew Chow <github@achow101.com>2023-06-01 13:09:08 -0400
commitba616b932cb9e9adb7eb9f1826caa62ce422a22d (patch)
tree032c9cf74574b1f29a39c79b76fc9495353188b9 /src/wallet/bdb.cpp
parent1d858b055daeea363e0450f327672658548be4c6 (diff)
downloadbitcoin-ba616b932cb9e9adb7eb9f1826caa62ce422a22d.tar.xz
wallet: Add GetPrefixCursor to DatabaseBatch
In order to get records beginning with a prefix, we will need a cursor specifically for that prefix. So add a GetPrefixCursor function and DatabaseCursor classes for dealing with those prefixes. Tested on each supported db engine. 1) Write two different key->value elements to db. 2) Create a new prefix cursor and walk-through every returned element, verifying that it gets parsed properly. 3) Try to move the cursor outside the filtered range: expect failure and flag complete=true. Co-Authored-By: Ryan Ofsky <ryan@ofsky.org> Co-Authored-By: furszy <matiasfurszyfer@protonmail.com>
Diffstat (limited to 'src/wallet/bdb.cpp')
-rw-r--r--src/wallet/bdb.cpp26
1 files changed, 22 insertions, 4 deletions
diff --git a/src/wallet/bdb.cpp b/src/wallet/bdb.cpp
index 7a1916ddc3..68abdcd81e 100644
--- a/src/wallet/bdb.cpp
+++ b/src/wallet/bdb.cpp
@@ -668,7 +668,8 @@ void BerkeleyDatabase::ReloadDbEnv()
env->ReloadDbEnv();
}
-BerkeleyCursor::BerkeleyCursor(BerkeleyDatabase& database, const BerkeleyBatch& batch)
+BerkeleyCursor::BerkeleyCursor(BerkeleyDatabase& database, const BerkeleyBatch& batch, Span<const std::byte> prefix)
+ : m_key_prefix(prefix.begin(), prefix.end())
{
if (!database.m_db.get()) {
throw std::runtime_error(STR_INTERNAL_BUG("BerkeleyDatabase does not exist"));
@@ -685,9 +686,15 @@ DatabaseCursor::Status BerkeleyCursor::Next(DataStream& ssKey, DataStream& ssVal
{
if (m_cursor == nullptr) return Status::FAIL;
// Read at cursor
- SafeDbt datKey;
+ SafeDbt datKey(m_key_prefix.data(), m_key_prefix.size());
SafeDbt datValue;
- int ret = m_cursor->get(datKey, datValue, DB_NEXT);
+ int ret = -1;
+ if (m_first && !m_key_prefix.empty()) {
+ ret = m_cursor->get(datKey, datValue, DB_SET_RANGE);
+ } else {
+ ret = m_cursor->get(datKey, datValue, DB_NEXT);
+ }
+ m_first = false;
if (ret == DB_NOTFOUND) {
return Status::DONE;
}
@@ -695,9 +702,14 @@ DatabaseCursor::Status BerkeleyCursor::Next(DataStream& ssKey, DataStream& ssVal
return Status::FAIL;
}
+ Span<const std::byte> raw_key = {AsBytePtr(datKey.get_data()), datKey.get_size()};
+ if (!m_key_prefix.empty() && std::mismatch(raw_key.begin(), raw_key.end(), m_key_prefix.begin(), m_key_prefix.end()).second != m_key_prefix.end()) {
+ return Status::DONE;
+ }
+
// Convert to streams
ssKey.clear();
- ssKey.write({AsBytePtr(datKey.get_data()), datKey.get_size()});
+ ssKey.write(raw_key);
ssValue.clear();
ssValue.write({AsBytePtr(datValue.get_data()), datValue.get_size()});
return Status::MORE;
@@ -716,6 +728,12 @@ std::unique_ptr<DatabaseCursor> BerkeleyBatch::GetNewCursor()
return std::make_unique<BerkeleyCursor>(m_database, *this);
}
+std::unique_ptr<DatabaseCursor> BerkeleyBatch::GetNewPrefixCursor(Span<const std::byte> prefix)
+{
+ if (!pdb) return nullptr;
+ return std::make_unique<BerkeleyCursor>(m_database, *this, prefix);
+}
+
bool BerkeleyBatch::TxnBegin()
{
if (!pdb || activeTxn)