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>
This commit is contained in:
Andrew Chow
2022-04-11 17:11:37 -04:00
committed by Andrew Chow
parent 1d858b055d
commit ba616b932c
10 changed files with 239 additions and 15 deletions

View File

@@ -92,6 +92,17 @@ 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<const std::byte> prefix; };
bool operator<(BytePrefix a, Span<const std::byte> b) { return a.prefix < b.subspan(0, std::min(a.prefix.size(), b.size())); }
bool operator<(Span<const std::byte> a, BytePrefix b) { return a.subspan(0, std::min(a.size(), b.prefix.size())) < b.prefix; }
MockableCursor::MockableCursor(const MockableData& records, bool pass, Span<const std::byte> prefix)
{
m_pass = pass;
std::tie(m_cursor, m_cursor_end) = records.equal_range(BytePrefix{prefix});
}
DatabaseCursor::Status MockableCursor::Next(DataStream& key, DataStream& value)
{
if (!m_pass) {
@@ -175,7 +186,7 @@ bool MockableBatch::ErasePrefix(Span<const std::byte> prefix)
return true;
}
std::unique_ptr<WalletDatabase> CreateMockableWalletDatabase(std::map<SerializeData, SerializeData> records)
std::unique_ptr<WalletDatabase> CreateMockableWalletDatabase(MockableData records)
{
return std::make_unique<MockableDatabase>(records);
}