Skip to content

Commit 9b1e39a

Browse files
committed
fix history_info
1 parent 444d49a commit 9b1e39a

File tree

1 file changed

+17
-10
lines changed

1 file changed

+17
-10
lines changed

crates/storage/provider/src/providers/state/historical.rs

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use reth_interfaces::provider::ProviderResult;
1414
use reth_primitives::{
1515
trie::AccountProof, Account, Address, BlockNumber, Bytecode, StorageKey, StorageValue, B256,
1616
};
17+
use std::fmt::Debug;
1718

1819
/// State provider for a given block number which takes a tx reference.
1920
///
@@ -109,36 +110,42 @@ impl<'b, TX: DbTx> HistoricalStateProviderRef<'b, TX> {
109110
// index, the first chunk for the next key will be returned so we filter out chunks that
110111
// have a different key.
111112
if let Some(chunk) = cursor.seek(key)?.filter(|(key, _)| key_filter(key)).map(|x| x.1 .0) {
112-
// Get the rank of the first entry after our block.
113-
let rank = chunk.rank(self.block_number);
113+
// Get the rank of the first entry before or equal to our block.
114+
let mut rank = chunk.rank(self.block_number);
114115

115-
let Some(block_number) = chunk.select(rank) else {
116-
// The chunk does not contain an entry for a write after our block. This can only
117-
// happen if this is the last chunk and so we need to look in the plain state.
118-
return Ok(HistoryInfo::InPlainState)
116+
// Adjust the rank, so that we have the rank of the first entry before our block
117+
if rank.checked_sub(1).and_then(|rank| chunk.select(rank)) == Some(self.block_number) {
118+
rank -= 1
119119
};
120120

121+
let block_number = chunk.select(rank);
122+
121123
// If our block is before the first entry in the index chunk and this first entry
122-
// doesn't equal to our block, it might be before the first write ever. To check, we
124+
// doesn't equal to our block it might be before the first write ever. To check, we
123125
// look at the previous entry and check if the key is the same.
124126
// This check is worth it, the `cursor.prev()` check is rarely triggered (the if will
125127
// short-circuit) and when it passes we save a full seek into the changeset/plain state
126128
// table.
127129
if rank == 0 &&
128-
block_number != self.block_number &&
130+
block_number != Some(self.block_number) &&
129131
!cursor.prev()?.is_some_and(|(key, _)| key_filter(&key))
130132
{
131-
if lowest_available_block_number.is_some() {
133+
if let (Some(_), Some(block_number)) = (lowest_available_block_number, block_number)
134+
{
132135
// The key may have been written, but due to pruning we may not have changesets
133136
// and history, so we need to make a changeset lookup.
134137
Ok(HistoryInfo::InChangeset(block_number))
135138
} else {
136139
// The key is written to, but only after our block.
137140
Ok(HistoryInfo::NotYetWritten)
138141
}
139-
} else {
142+
} else if let Some(block_number) = block_number {
140143
// The chunk contains an entry for a write after our block, return it.
141144
Ok(HistoryInfo::InChangeset(block_number))
145+
} else {
146+
// The chunk does not contain an entry for a write after our block. This can only
147+
// happen if this is the last chunk and so we need to look in the plain state.
148+
Ok(HistoryInfo::InPlainState)
142149
}
143150
} else if lowest_available_block_number.is_some() {
144151
// The key may have been written, but due to pruning we may not have changesets and

0 commit comments

Comments
 (0)