diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp index ea06767e9bc..a5a5f8ec6f2 100644 --- a/src/wallet/db.cpp +++ b/src/wallet/db.cpp @@ -16,6 +16,9 @@ #include namespace wallet { +bool operator<(BytePrefix a, Span b) { return a.prefix < b.subspan(0, std::min(a.prefix.size(), b.size())); } +bool operator<(Span a, BytePrefix b) { return a.subspan(0, std::min(a.size(), b.prefix.size())) < b.prefix; } + std::vector ListDatabases(const fs::path& wallet_dir) { std::vector paths; diff --git a/src/wallet/db.h b/src/wallet/db.h index 084fcadc24a..648adff5fe4 100644 --- a/src/wallet/db.h +++ b/src/wallet/db.h @@ -20,6 +20,12 @@ class ArgsManager; struct bilingual_str; namespace wallet { +// BytePrefix compares equality with other byte spans that begin with the same prefix. +struct BytePrefix { + Span prefix; +}; +bool operator<(BytePrefix a, Span b); +bool operator<(Span a, BytePrefix b); class DatabaseCursor { diff --git a/src/wallet/migrate.cpp b/src/wallet/migrate.cpp index e567cb0f518..f922d99a172 100644 --- a/src/wallet/migrate.cpp +++ b/src/wallet/migrate.cpp @@ -21,17 +21,42 @@ bool BerkeleyRODatabase::Backup(const std::string& dest) const bool BerkeleyROBatch::ReadKey(DataStream&& key, DataStream& value) { - return false; + SerializeData key_data{key.begin(), key.end()}; + const auto it{m_database.m_records.find(key_data)}; + if (it == m_database.m_records.end()) { + return false; + } + auto val = it->second; + value.clear(); + value.write(Span(val)); + return true; } bool BerkeleyROBatch::HasKey(DataStream&& key) { - return false; + SerializeData key_data{key.begin(), key.end()}; + return m_database.m_records.count(key_data) > 0; +} + +BerkeleyROCursor::BerkeleyROCursor(const BerkeleyRODatabase& database, Span prefix) + : m_database(database) +{ + std::tie(m_cursor, m_cursor_end) = m_database.m_records.equal_range(BytePrefix{prefix}); } DatabaseCursor::Status BerkeleyROCursor::Next(DataStream& ssKey, DataStream& ssValue) { - return DatabaseCursor::Status::FAIL; + if (m_cursor == m_cursor_end) { + return DatabaseCursor::Status::DONE; + } + ssKey.write(Span(m_cursor->first)); + ssValue.write(Span(m_cursor->second)); + m_cursor++; + return DatabaseCursor::Status::MORE; } +std::unique_ptr BerkeleyROBatch::GetNewPrefixCursor(Span prefix) +{ + return std::make_unique(m_database, prefix); +} } // namespace wallet diff --git a/src/wallet/migrate.h b/src/wallet/migrate.h index de7082e8a04..a3b0d78d02e 100644 --- a/src/wallet/migrate.h +++ b/src/wallet/migrate.h @@ -10,6 +10,9 @@ #include namespace wallet { + +using BerkeleyROData = std::map>; + /** * A class representing a BerkeleyDB file from which we can only read records. * This is used only for migration of legacy to descriptor wallets @@ -27,6 +30,8 @@ public: } ~BerkeleyRODatabase(){}; + BerkeleyROData m_records; + /** Open the database if it is not already opened. */ void Open() override; @@ -69,7 +74,15 @@ public: class BerkeleyROCursor : public DatabaseCursor { +private: + const BerkeleyRODatabase& m_database; + BerkeleyROData::const_iterator m_cursor; + BerkeleyROData::const_iterator m_cursor_end; + public: + explicit BerkeleyROCursor(const BerkeleyRODatabase& database, Span prefix = {}); + ~BerkeleyROCursor() {} + Status Next(DataStream& key, DataStream& value) override; }; @@ -97,8 +110,8 @@ public: void Flush() override {} void Close() override {} - std::unique_ptr GetNewCursor() override { return std::make_unique(); } - std::unique_ptr GetNewPrefixCursor(Span prefix) override { return std::make_unique(); } + std::unique_ptr GetNewCursor() override { return std::make_unique(m_database); } + std::unique_ptr GetNewPrefixCursor(Span prefix) override; bool TxnBegin() override { return false; } bool TxnCommit() override { return false; } bool TxnAbort() override { return false; } diff --git a/src/wallet/test/util.cpp b/src/wallet/test/util.cpp index 49d206f4090..b21a9a601d1 100644 --- a/src/wallet/test/util.cpp +++ b/src/wallet/test/util.cpp @@ -93,11 +93,6 @@ CTxDestination getNewDestination(CWallet& w, OutputType output_type) return *Assert(w.GetNewDestination(output_type, "")); } -// BytePrefix compares equality with other byte spans that begin with the same prefix. -struct BytePrefix { Span prefix; }; -bool operator<(BytePrefix a, Span b) { return a.prefix < b.subspan(0, std::min(a.prefix.size(), b.size())); } -bool operator<(Span a, BytePrefix b) { return a.subspan(0, std::min(a.size(), b.prefix.size())) < b.prefix; } - MockableCursor::MockableCursor(const MockableData& records, bool pass, Span prefix) { m_pass = pass;