mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 19:09:54 +00:00
fix(provider): check list size before calling range.nth (#10460)
This commit is contained in:
@ -126,6 +126,53 @@ where
|
|||||||
(start, end)
|
(start, end)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Fetches a range of data from both in-memory state and storage.
|
||||||
|
///
|
||||||
|
/// - `fetch_db_range`: Retrieves a range of items from the database.
|
||||||
|
/// - `map_block_state_item`: Maps a block number to an item in memory. Stops fetching if `None`
|
||||||
|
/// is returned.
|
||||||
|
fn fetch_db_mem_range<T, F, G, P>(
|
||||||
|
&self,
|
||||||
|
range: impl RangeBounds<BlockNumber>,
|
||||||
|
fetch_db_range: F,
|
||||||
|
map_block_state_item: G,
|
||||||
|
mut predicate: P,
|
||||||
|
) -> ProviderResult<Vec<T>>
|
||||||
|
where
|
||||||
|
F: FnOnce(RangeInclusive<BlockNumber>, &mut P) -> ProviderResult<Vec<T>>,
|
||||||
|
G: Fn(BlockNumber, &mut P) -> Option<T>,
|
||||||
|
P: FnMut(&T) -> bool,
|
||||||
|
{
|
||||||
|
let (start, end) = self.convert_range_bounds(range, || {
|
||||||
|
self.canonical_in_memory_state.get_canonical_block_number()
|
||||||
|
});
|
||||||
|
let mut range = start..=end;
|
||||||
|
let mut items = Vec::with_capacity((end - start + 1) as usize);
|
||||||
|
|
||||||
|
// First, fetch the items from the database
|
||||||
|
let mut db_items = fetch_db_range(range.clone(), &mut predicate)?;
|
||||||
|
|
||||||
|
if !db_items.is_empty() {
|
||||||
|
items.append(&mut db_items);
|
||||||
|
|
||||||
|
// Advance the range iterator by the number of items fetched from the database
|
||||||
|
range.nth(items.len() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch the remaining items from the in-memory state
|
||||||
|
for num in range {
|
||||||
|
// TODO: there might be an update between loop iterations, we
|
||||||
|
// need to handle that situation.
|
||||||
|
if let Some(item) = map_block_state_item(num, &mut predicate) {
|
||||||
|
items.push(item);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(items)
|
||||||
|
}
|
||||||
|
|
||||||
/// This uses a given [`BlockState`] to initialize a state provider for that block.
|
/// This uses a given [`BlockState`] to initialize a state provider for that block.
|
||||||
fn block_state_provider(
|
fn block_state_provider(
|
||||||
&self,
|
&self,
|
||||||
@ -285,32 +332,16 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn headers_range(&self, range: impl RangeBounds<BlockNumber>) -> ProviderResult<Vec<Header>> {
|
fn headers_range(&self, range: impl RangeBounds<BlockNumber>) -> ProviderResult<Vec<Header>> {
|
||||||
let (start, end) = self.convert_range_bounds(range, || {
|
self.fetch_db_mem_range(
|
||||||
self.canonical_in_memory_state.get_canonical_block_number()
|
range,
|
||||||
});
|
|range, _| self.database.headers_range(range),
|
||||||
let mut range = start..=end;
|
|num, _| {
|
||||||
let mut headers = Vec::with_capacity((end - start + 1) as usize);
|
self.canonical_in_memory_state
|
||||||
|
.state_by_number(num)
|
||||||
// First, fetch the headers from the database
|
.map(|block_state| block_state.block().block().header.header().clone())
|
||||||
let mut db_headers = self.database.headers_range(range.clone())?;
|
},
|
||||||
|
|_| true,
|
||||||
// Advance the range iterator by the number of headers fetched from the database
|
)
|
||||||
range.nth(db_headers.len() - 1);
|
|
||||||
|
|
||||||
headers.append(&mut db_headers);
|
|
||||||
|
|
||||||
// Fetch the remaining headers from the in-memory state
|
|
||||||
for num in range {
|
|
||||||
if let Some(block_state) = self.canonical_in_memory_state.state_by_number(num) {
|
|
||||||
// TODO: there might be an update between loop iterations, we
|
|
||||||
// need to handle that situation.
|
|
||||||
headers.push(block_state.block().block().header.header().clone());
|
|
||||||
} else {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(headers)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sealed_header(&self, number: BlockNumber) -> ProviderResult<Option<SealedHeader>> {
|
fn sealed_header(&self, number: BlockNumber) -> ProviderResult<Option<SealedHeader>> {
|
||||||
@ -325,69 +356,34 @@ where
|
|||||||
&self,
|
&self,
|
||||||
range: impl RangeBounds<BlockNumber>,
|
range: impl RangeBounds<BlockNumber>,
|
||||||
) -> ProviderResult<Vec<SealedHeader>> {
|
) -> ProviderResult<Vec<SealedHeader>> {
|
||||||
let (start, end) = self.convert_range_bounds(range, || {
|
self.fetch_db_mem_range(
|
||||||
self.canonical_in_memory_state.get_canonical_block_number()
|
range,
|
||||||
});
|
|range, _| self.database.sealed_headers_range(range),
|
||||||
let mut range = start..=end;
|
|num, _| {
|
||||||
let mut sealed_headers = Vec::with_capacity((end - start + 1) as usize);
|
self.canonical_in_memory_state
|
||||||
|
.state_by_number(num)
|
||||||
// First, fetch the headers from the database
|
.map(|block_state| block_state.block().block().header.clone())
|
||||||
let mut db_headers = self.database.sealed_headers_range(range.clone())?;
|
},
|
||||||
|
|_| true,
|
||||||
// Advance the range iterator by the number of headers fetched from the database
|
)
|
||||||
range.nth(db_headers.len() - 1);
|
|
||||||
|
|
||||||
sealed_headers.append(&mut db_headers);
|
|
||||||
|
|
||||||
// Fetch the remaining headers from the in-memory state
|
|
||||||
for num in range {
|
|
||||||
if let Some(block_state) = self.canonical_in_memory_state.state_by_number(num) {
|
|
||||||
// TODO: there might be an update between loop iterations, we
|
|
||||||
// need to handle that situation.
|
|
||||||
sealed_headers.push(block_state.block().block().header.clone());
|
|
||||||
} else {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(sealed_headers)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sealed_headers_while(
|
fn sealed_headers_while(
|
||||||
&self,
|
&self,
|
||||||
range: impl RangeBounds<BlockNumber>,
|
range: impl RangeBounds<BlockNumber>,
|
||||||
mut predicate: impl FnMut(&SealedHeader) -> bool,
|
predicate: impl FnMut(&SealedHeader) -> bool,
|
||||||
) -> ProviderResult<Vec<SealedHeader>> {
|
) -> ProviderResult<Vec<SealedHeader>> {
|
||||||
let (start, end) = self.convert_range_bounds(range, || {
|
self.fetch_db_mem_range(
|
||||||
self.canonical_in_memory_state.get_canonical_block_number()
|
range,
|
||||||
});
|
|range, predicate| self.database.sealed_headers_while(range, predicate),
|
||||||
let mut range = start..=end;
|
|num, predicate| {
|
||||||
let mut sealed_headers = Vec::with_capacity((end - start + 1) as usize);
|
self.canonical_in_memory_state
|
||||||
|
.state_by_number(num)
|
||||||
// First, fetch the headers from the database
|
.map(|block_state| block_state.block().block().header.clone())
|
||||||
let mut db_headers = self.database.sealed_headers_while(range.clone(), &mut predicate)?;
|
.filter(|header| predicate(header))
|
||||||
|
},
|
||||||
// Advance the range iterator by the number of headers fetched from the database
|
predicate,
|
||||||
range.nth(db_headers.len() - 1);
|
)
|
||||||
|
|
||||||
sealed_headers.append(&mut db_headers);
|
|
||||||
|
|
||||||
// Fetch the remaining headers from the in-memory state
|
|
||||||
for num in range {
|
|
||||||
if let Some(block_state) = self.canonical_in_memory_state.state_by_number(num) {
|
|
||||||
let header = block_state.block().block().header.clone();
|
|
||||||
if !predicate(&header) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
// TODO: there might be an update between loop iterations, we
|
|
||||||
// need to handle that situation.
|
|
||||||
sealed_headers.push(header);
|
|
||||||
} else {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(sealed_headers)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -408,30 +404,16 @@ where
|
|||||||
start: BlockNumber,
|
start: BlockNumber,
|
||||||
end: BlockNumber,
|
end: BlockNumber,
|
||||||
) -> ProviderResult<Vec<B256>> {
|
) -> ProviderResult<Vec<B256>> {
|
||||||
let mut range = start..=end;
|
self.fetch_db_mem_range(
|
||||||
|
start..=end,
|
||||||
let mut hashes = Vec::with_capacity((end - start + 1) as usize);
|
|range, _| self.database.canonical_hashes_range(*range.start(), *range.end()),
|
||||||
|
|num, _| {
|
||||||
// First, fetch the hashes from the database
|
self.canonical_in_memory_state
|
||||||
let mut db_hashes = self.database.canonical_hashes_range(start, end)?;
|
.state_by_number(num)
|
||||||
|
.map(|block_state| block_state.hash())
|
||||||
// Advance the range iterator by the number of blocks fetched from the database
|
},
|
||||||
range.nth(db_hashes.len() - 1);
|
|_| true,
|
||||||
|
)
|
||||||
hashes.append(&mut db_hashes);
|
|
||||||
|
|
||||||
// Fetch the remaining blocks from the in-memory state
|
|
||||||
for num in range {
|
|
||||||
if let Some(block_state) = self.canonical_in_memory_state.state_by_number(num) {
|
|
||||||
// TODO: there might be an update between loop iterations, we
|
|
||||||
// need to handle that situation.
|
|
||||||
hashes.push(block_state.hash());
|
|
||||||
} else {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(hashes)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -629,89 +611,53 @@ where
|
|||||||
self.database.sealed_block_with_senders(id, transaction_kind)
|
self.database.sealed_block_with_senders(id, transaction_kind)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn block_range(&self, mut range: RangeInclusive<BlockNumber>) -> ProviderResult<Vec<Block>> {
|
fn block_range(&self, range: RangeInclusive<BlockNumber>) -> ProviderResult<Vec<Block>> {
|
||||||
let capacity = (range.end() - range.start() + 1) as usize;
|
self.fetch_db_mem_range(
|
||||||
let mut blocks = Vec::with_capacity(capacity);
|
range,
|
||||||
|
|range, _| self.database.block_range(range),
|
||||||
// First, fetch the blocks from the database
|
|num, _| {
|
||||||
let mut database_blocks = self.database.block_range(range.clone())?;
|
self.canonical_in_memory_state
|
||||||
blocks.append(&mut database_blocks);
|
.state_by_number(num)
|
||||||
|
.map(|block_state| block_state.block().block().clone().unseal())
|
||||||
// Advance the range iterator by the number of blocks fetched from the database
|
},
|
||||||
range.nth(blocks.len() - 1);
|
|_| true,
|
||||||
|
)
|
||||||
// Fetch the remaining blocks from the in-memory state
|
|
||||||
for num in range {
|
|
||||||
if let Some(block_state) = self.canonical_in_memory_state.state_by_number(num) {
|
|
||||||
// TODO: there might be an update between loop iterations, we
|
|
||||||
// need to handle that situation.
|
|
||||||
blocks.push(block_state.block().block().clone().unseal());
|
|
||||||
} else {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(blocks)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn block_with_senders_range(
|
fn block_with_senders_range(
|
||||||
&self,
|
&self,
|
||||||
mut range: RangeInclusive<BlockNumber>,
|
range: RangeInclusive<BlockNumber>,
|
||||||
) -> ProviderResult<Vec<BlockWithSenders>> {
|
) -> ProviderResult<Vec<BlockWithSenders>> {
|
||||||
let capacity = (range.end() - range.start() + 1) as usize;
|
self.fetch_db_mem_range(
|
||||||
let mut blocks = Vec::with_capacity(capacity);
|
range,
|
||||||
|
|range, _| self.database.block_with_senders_range(range),
|
||||||
// First, fetch the blocks from the database
|
|num, _| {
|
||||||
let mut database_blocks = self.database.block_with_senders_range(range.clone())?;
|
self.canonical_in_memory_state.state_by_number(num).map(|block_state| {
|
||||||
blocks.append(&mut database_blocks);
|
let block = block_state.block().block().clone();
|
||||||
|
let senders = block_state.block().senders().clone();
|
||||||
// Advance the range iterator by the number of blocks fetched from the database
|
BlockWithSenders { block: block.unseal(), senders }
|
||||||
range.nth(blocks.len() - 1);
|
})
|
||||||
|
},
|
||||||
// Fetch the remaining blocks from the in-memory state
|
|_| true,
|
||||||
for num in range {
|
)
|
||||||
if let Some(block_state) = self.canonical_in_memory_state.state_by_number(num) {
|
|
||||||
let block = block_state.block().block().clone();
|
|
||||||
let senders = block_state.block().senders().clone();
|
|
||||||
// TODO: there might be an update between loop iterations, we
|
|
||||||
// need to handle that situation.
|
|
||||||
blocks.push(BlockWithSenders { block: block.unseal(), senders });
|
|
||||||
} else {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(blocks)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sealed_block_with_senders_range(
|
fn sealed_block_with_senders_range(
|
||||||
&self,
|
&self,
|
||||||
mut range: RangeInclusive<BlockNumber>,
|
range: RangeInclusive<BlockNumber>,
|
||||||
) -> ProviderResult<Vec<SealedBlockWithSenders>> {
|
) -> ProviderResult<Vec<SealedBlockWithSenders>> {
|
||||||
let capacity = (range.end() - range.start() + 1) as usize;
|
self.fetch_db_mem_range(
|
||||||
let mut blocks = Vec::with_capacity(capacity);
|
range,
|
||||||
|
|range, _| self.database.sealed_block_with_senders_range(range),
|
||||||
// First, fetch the blocks from the database
|
|num, _| {
|
||||||
let mut database_blocks = self.database.sealed_block_with_senders_range(range.clone())?;
|
self.canonical_in_memory_state.state_by_number(num).map(|block_state| {
|
||||||
blocks.append(&mut database_blocks);
|
let block = block_state.block().block().clone();
|
||||||
|
let senders = block_state.block().senders().clone();
|
||||||
// Advance the range iterator by the number of blocks fetched from the database
|
SealedBlockWithSenders { block, senders }
|
||||||
range.nth(blocks.len() - 1);
|
})
|
||||||
|
},
|
||||||
// Fetch the remaining blocks from the in-memory state
|
|_| true,
|
||||||
for num in range {
|
)
|
||||||
if let Some(block_state) = self.canonical_in_memory_state.state_by_number(num) {
|
|
||||||
let block = block_state.block().block().clone();
|
|
||||||
let senders = block_state.block().senders().clone();
|
|
||||||
// TODO: there might be an update between loop iterations, we
|
|
||||||
// need to handle that situation.
|
|
||||||
blocks.push(SealedBlockWithSenders { block, senders });
|
|
||||||
} else {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(blocks)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user