@@ -24,23 +24,16 @@ BTree::BTree(
2424
2525using CompareResult = std::pair<int , BytesOrByteView>;
2626
27- static CompareResult compare_key (
27+ static std::optional< CompareResult> compare_key (
2828 ByteView key,
2929 BTree::DataIndex key_index,
3030 const BTree::KeyValueIndex& index) {
3131 auto data_key = index.lookup_key (key_index);
32- ensure (data_key.has_value (), [&] { return " out-of-bounds key=" + to_hex (key) + " data_index=" + std::to_string (key_index); });
32+ if (!data_key) {
33+ return std::nullopt ;
34+ }
3335 int cmp = ByteView{*data_key}.compare (key);
34- return {cmp, std::move (*data_key)};
35- }
36-
37- static BTree::KeyValueIndex::LookupResult lookup_key_value (
38- ByteView key,
39- BTree::DataIndex key_index,
40- const BTree::KeyValueIndex& index) {
41- auto result = index.lookup_key_value (key_index, key);
42- ensure (result.has_value (), [&] { return " out-of-bounds key=" + to_hex (key) + " data_index=" + std::to_string (key_index); });
43- return std::move (*result);
36+ return CompareResult{cmp, std::move (*data_key)};
4437}
4538
4639BTree::SeekResult BTree::seek (ByteView seek_key, const KeyValueIndex& index) {
@@ -55,8 +48,12 @@ BTree::SeekResult BTree::seek(ByteView seek_key, const KeyValueIndex& index) {
5548 auto [_, left_index, right_index] = binary_search_in_cache (seek_key); // left_index == right_index when key is found
5649 uint64_t median = 0 ;
5750 while (left_index < right_index) {
58- if (right_index - left_index <= kDefaultBtreeStartSkip ) { // found small range, faster to scan now
59- const auto [cmp, key] = compare_key (seek_key, left_index, index);
51+ if (right_index - left_index <= kDefaultBtreeStartSkip ) { // found a small range, faster to scan now
52+ const auto cmp_result = compare_key (seek_key, left_index, index);
53+ if (!cmp_result) {
54+ return {/* found=*/ false , {}, {}, 0 };
55+ }
56+ const auto [cmp, key] = *cmp_result;
6057 if (cmp == 0 ) {
6158 right_index = left_index;
6259 break ;
@@ -71,7 +68,11 @@ BTree::SeekResult BTree::seek(ByteView seek_key, const KeyValueIndex& index) {
7168 break ;
7269 }
7370 median = (left_index + right_index) >> 1 ;
74- const auto [cmp, key] = compare_key (seek_key, median, index);
71+ const auto cmp_result = compare_key (seek_key, median, index);
72+ if (!cmp_result) {
73+ return {/* found=*/ false , {}, {}, 0 };
74+ }
75+ const auto [cmp, key] = *cmp_result;
7576 if (cmp == 0 ) {
7677 left_index = right_index = median;
7778 break ;
@@ -107,7 +108,7 @@ std::optional<BytesOrByteView> BTree::get(ByteView key, const KeyValueIndex& ind
107108 }
108109 auto [_, left_index, right_index] = binary_search_in_cache (key); // left_index == right_index when key is found
109110 while (left_index < right_index) {
110- if (right_index - left_index <= kDefaultBtreeStartSkip ) { // found small range, faster to scan now
111+ if (right_index - left_index <= kDefaultBtreeStartSkip ) { // found a small range, faster to scan now
111112 auto value = index.advance_key_value (left_index, key, right_index - left_index);
112113 if (!value) {
113114 left_index = right_index;
@@ -116,7 +117,11 @@ std::optional<BytesOrByteView> BTree::get(ByteView key, const KeyValueIndex& ind
116117 return value;
117118 }
118119 const uint64_t median = (left_index + right_index) >> 1 ;
119- auto [cmp, optional_v] = lookup_key_value (key, median, index);
120+ const auto lookup_result = index.lookup_key_value (median, key);
121+ if (!lookup_result) {
122+ return std::nullopt ;
123+ }
124+ const auto [cmp, optional_v] = *lookup_result;
120125 if (cmp == 0 ) {
121126 SILKWORM_ASSERT (optional_v);
122127 return optional_v;
@@ -127,7 +132,11 @@ std::optional<BytesOrByteView> BTree::get(ByteView key, const KeyValueIndex& ind
127132 left_index = median + 1 ;
128133 }
129134 }
130- auto [cmp, optional_v] = lookup_key_value (key, left_index, index);
135+ const auto lookup_result = index.lookup_key_value (left_index, key);
136+ if (!lookup_result) {
137+ return std::nullopt ;
138+ }
139+ const auto [cmp, optional_v] = *lookup_result;
131140 if (cmp != 0 ) {
132141 return std::nullopt ;
133142 }
@@ -157,7 +166,9 @@ void BTree::warmup(const KeyValueIndex& index) {
157166 const size_t step = num_nodes_ < fanout_ ? 1 : fanout_; // cache all keys if less than M
158167 for (size_t i{step}; i < num_nodes_; i += step) {
159168 const size_t data_index = i - 1 ;
160- auto [_, key] = compare_key ({}, data_index, index);
169+ auto cmp_result = compare_key ({}, data_index, index);
170+ if (!cmp_result) continue ;
171+ auto [_, key] = *cmp_result;
161172 cache_.emplace_back (Node{data_index, Bytes{key}});
162173 cached_bytes += sizeof (Node) + ByteView{key}.size ();
163174 }
@@ -185,7 +196,11 @@ BTree::Nodes BTree::decode_nodes(std::span<uint8_t> encoded_nodes) {
185196
186197void BTree::check_against_data_keys (const KeyValueIndex& index) {
187198 for (const auto & node : cache_) {
188- const auto [cmp, key] = compare_key (node.key , node.key_index , index);
199+ const auto cmp_result = compare_key (node.key , node.key_index , index);
200+ ensure (cmp_result.has_value (), [&] {
201+ return " out-of-bounds key=" + to_hex (node.key ) + " data_index=" + std::to_string (node.key_index );
202+ });
203+ const auto [cmp, key] = *cmp_result;
189204 ensure (cmp == 0 , [&]() {
190205 return " key mismatch node.key=" + to_hex (node.key ) +
191206 " key=" + to_hex (key) +
0 commit comments