Skip to content

Commit 0b8494d

Browse files
rabbitson87claude
andcommitted
Revert "perf(rpc): search the block log for a record instead of scanning it"
This reverts 539d8da. The change duplicates #87, which was opened two days earlier and makes the same argument: `record_for_hash` has the height from the block tree, the log is ordered by height, so the lookup is a search. #87 also covers `Context::block_hash_at_height`, which 539d8da missed. What 539d8da had and #87 does not - a benchmark, the sweep-against-a-scan equivalence tests, `block_by_height_without_an_applied_tip_reads_the_log`, and five further mutations - moves to #87 rather than being dropped. This branch keeps only the chain-info fold, which nothing else covers. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent 539d8da commit 0b8494d

5 files changed

Lines changed: 52 additions & 455 deletions

File tree

crates/node/src/block_source.rs

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use bitcoin::hex::FromHex as _;
1414
use bitcoin_rs_chain::{BlockTree, NodeId, TipSnapshot};
1515
use bitcoin_rs_index::BlockSource;
1616
use bitcoin_rs_primitives::Hash256;
17-
use bitcoin_rs_rpc::{BlockBodySource, BlockLog};
17+
use bitcoin_rs_rpc::{BlockBodySource, BlockLog, BlockRecord};
1818
use parking_lot::RwLock;
1919

2020
/// Reads decoded Bitcoin blocks from the shared in-memory log.
@@ -82,7 +82,7 @@ impl BlockSource for NodeBlockSource {
8282
tree.read().active_node_at_height(height)?.hash
8383
} else {
8484
let guard = self.blocks.read();
85-
guard.record_at_height(height)?.hash
85+
record_at_height(&guard, height)?.hash
8686
};
8787
self.resolve_block_by_hash(height, active_hash)
8888
}
@@ -98,7 +98,7 @@ impl BlockSource for NodeBlockSource {
9898
tree.read().active_node_at_height(height)?.hash
9999
} else {
100100
let guard = self.blocks.read();
101-
guard.record_at_height(height)?.hash
101+
record_at_height(&guard, height)?.hash
102102
};
103103
source.block_body_range(height, hash, offset, len)
104104
}
@@ -138,7 +138,7 @@ impl NodeBlockSource {
138138
fn cached_body_bytes(&self, height: u32, hash: Hash256) -> Option<Vec<u8>> {
139139
let block_hex = {
140140
let guard = self.blocks.read();
141-
let record = guard.record_at_height_hash(height, hash)?;
141+
let record = record_at_height_hash(&guard, height, hash)?;
142142
(!record.block_hex.is_empty()).then(|| record.block_hex.clone())
143143
}?;
144144
Vec::<u8>::from_hex(&block_hex).ok()
@@ -298,6 +298,47 @@ fn serialized_header(
298298
})
299299
}
300300

301+
fn record_at_height(records: &[BlockRecord], height: u32) -> Option<&BlockRecord> {
302+
if let Ok(index) = usize::try_from(height)
303+
&& let Some(record) = records.get(index)
304+
&& record.height == height
305+
&& index
306+
.checked_sub(1)
307+
.and_then(|previous| records.get(previous))
308+
.is_none_or(|previous| previous.height < height)
309+
{
310+
return Some(record);
311+
}
312+
313+
let mut index = records
314+
.binary_search_by_key(&height, |record| record.height)
315+
.ok()?;
316+
while index > 0 && records[index.saturating_sub(1)].height == height {
317+
index = index.saturating_sub(1);
318+
}
319+
records.get(index)
320+
}
321+
322+
fn record_at_height_hash(
323+
records: &[BlockRecord],
324+
height: u32,
325+
hash: Hash256,
326+
) -> Option<&BlockRecord> {
327+
let mut index = records
328+
.binary_search_by_key(&height, |record| record.height)
329+
.ok()?;
330+
while index > 0 && records[index.saturating_sub(1)].height == height {
331+
index = index.saturating_sub(1);
332+
}
333+
while index < records.len() && records[index].height == height {
334+
if records[index].hash == hash {
335+
return Some(&records[index]);
336+
}
337+
index += 1;
338+
}
339+
None
340+
}
341+
301342
#[cfg(test)]
302343
mod tests {
303344
use super::*;
@@ -306,7 +347,6 @@ mod tests {
306347
use bitcoin::consensus::encode::serialize;
307348
use bitcoin_rs_chain::NodeStatus;
308349
use bitcoin_rs_primitives::Hash256;
309-
use bitcoin_rs_rpc::BlockRecord;
310350
use std::error::Error;
311351

312352
type TestResult = Result<(), Box<dyn Error>>;

crates/rpc/Cargo.toml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,3 @@ criterion.workspace = true
5252
[[bench]]
5353
name = "chaininfo"
5454
harness = false
55-
56-
[[bench]]
57-
name = "blocklookup"
58-
harness = false

crates/rpc/benches/blocklookup.rs

Lines changed: 0 additions & 112 deletions
This file was deleted.

0 commit comments

Comments
 (0)