|
3 | 3 |
|
4 | 4 | use std::{ |
5 | 5 | collections::{BTreeMap, BTreeSet, HashMap, HashSet}, |
6 | | - ops::RangeBounds, |
7 | 6 | sync::Arc, |
8 | 7 | }; |
9 | 8 |
|
10 | 9 | use linera_base::{ |
11 | 10 | crypto::{CryptoHash, ValidatorPublicKey}, |
12 | 11 | data_types::{ |
13 | | - ApplicationDescription, ApplicationPermissions, ArithmeticError, Blob, BlockHeight, |
14 | | - BlockHeightRangeBounds as _, Epoch, OracleResponse, Timestamp, |
| 12 | + ApplicationDescription, ApplicationPermissions, ArithmeticError, Blob, BlockHeight, Epoch, |
| 13 | + OracleResponse, Timestamp, |
15 | 14 | }, |
16 | 15 | ensure, |
17 | 16 | identifiers::{AccountOwner, ApplicationId, BlobType, ChainId, StreamId}, |
@@ -1056,43 +1055,37 @@ where |
1056 | 1055 | } |
1057 | 1056 |
|
1058 | 1057 | /// Returns the hashes of all blocks we have in the given range. |
| 1058 | + /// |
| 1059 | + /// If the input heights are in ascending order, the hashes will be in the same order. |
| 1060 | + /// Otherwise they may be unordered. |
1059 | 1061 | #[instrument(skip_all, fields( |
1060 | 1062 | chain_id = %self.chain_id(), |
1061 | 1063 | next_block_height = %self.tip_state.get().next_block_height, |
1062 | | - start_height = ?range.start_bound(), |
1063 | | - end_height = ?range.end_bound() |
1064 | 1064 | ))] |
1065 | 1065 | pub async fn block_hashes( |
1066 | 1066 | &self, |
1067 | | - range: impl RangeBounds<BlockHeight>, |
| 1067 | + heights: impl IntoIterator<Item = BlockHeight>, |
1068 | 1068 | ) -> Result<Vec<CryptoHash>, ChainError> { |
1069 | 1069 | let next_height = self.tip_state.get().next_block_height; |
1070 | | - // If the range is not empty, it can always be represented as start..=end. |
1071 | | - let Some((start, end)) = range.to_inclusive() else { |
1072 | | - return Ok(Vec::new()); |
1073 | | - }; |
1074 | 1070 | // Everything up to (excluding) next_height is in confirmed_log. |
1075 | | - let mut hashes = if let Ok(last_height) = next_height.try_sub_one() { |
1076 | | - let usize_start = usize::try_from(start)?; |
1077 | | - let usize_end = usize::try_from(end.min(last_height))?; |
1078 | | - self.confirmed_log.read(usize_start..=usize_end).await? |
1079 | | - } else { |
1080 | | - Vec::new() |
1081 | | - }; |
| 1071 | + let (confirmed_heights, unconfirmed_heights) = heights |
| 1072 | + .into_iter() |
| 1073 | + .partition::<Vec<_>, _>(|height| *height < next_height); |
| 1074 | + let confirmed_indices = confirmed_heights |
| 1075 | + .into_iter() |
| 1076 | + .map(|height| usize::try_from(height.0).map_err(|_| ArithmeticError::Overflow)) |
| 1077 | + .collect::<Result<_, _>>()?; |
| 1078 | + let confirmed_hashes = self.confirmed_log.multi_get(confirmed_indices).await?; |
1082 | 1079 | // Everything after (including) next_height in preprocessed_blocks if we have it. |
1083 | | - let block_heights = (start.max(next_height).0..=end.0) |
1084 | | - .map(BlockHeight) |
1085 | | - .collect::<Vec<_>>(); |
1086 | | - for hash in self |
| 1080 | + let unconfirmed_hashes = self |
1087 | 1081 | .preprocessed_blocks |
1088 | | - .multi_get(&block_heights) |
1089 | | - .await? |
| 1082 | + .multi_get(&unconfirmed_heights) |
| 1083 | + .await?; |
| 1084 | + Ok(confirmed_hashes |
1090 | 1085 | .into_iter() |
| 1086 | + .chain(unconfirmed_hashes) |
1091 | 1087 | .flatten() |
1092 | | - { |
1093 | | - hashes.push(hash); |
1094 | | - } |
1095 | | - Ok(hashes) |
| 1088 | + .collect()) |
1096 | 1089 | } |
1097 | 1090 |
|
1098 | 1091 | /// Resets the chain manager for the next block height. |
|
0 commit comments