Skip to content

Commit

Permalink
Add performance improvements to single address endpoints
Browse files Browse the repository at this point in the history
  • Loading branch information
junderw committed Oct 9, 2024
1 parent 0e39040 commit b7d9b3a
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 41 deletions.
33 changes: 25 additions & 8 deletions src/new_index/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -507,10 +507,17 @@ impl ChainQuery {
&TxHistoryRow::prefix_height(code, hash, start_height as u32),
)
}
fn history_iter_scan_reverse(&self, code: u8, hash: &[u8]) -> ReverseScanIterator {
fn history_iter_scan_reverse(
&self,
code: u8,
hash: &[u8],
start_height: Option<u32>,
) -> ReverseScanIterator {
self.store.history_db.iter_scan_reverse(
&TxHistoryRow::filter(code, hash),
&TxHistoryRow::prefix_end(code, hash),
&start_height.map_or(TxHistoryRow::prefix_end(code, hash), |start_height| {
TxHistoryRow::prefix_height_end(code, hash, start_height)
}),
)
}
fn history_iter_scan_group_reverse(
Expand Down Expand Up @@ -631,22 +638,24 @@ impl ChainQuery {
&self,
scripthash: &[u8],
last_seen_txid: Option<&Txid>,
start_height: Option<u32>,
limit: usize,
) -> Vec<TxHistorySummary> {
// scripthash lookup
self._summary(b'H', scripthash, last_seen_txid, limit)
self._summary(b'H', scripthash, last_seen_txid, start_height, limit)
}

fn _summary(
&self,
code: u8,
hash: &[u8],
last_seen_txid: Option<&Txid>,
start_height: Option<u32>,
limit: usize,
) -> Vec<TxHistorySummary> {
let _timer_scan = self.start_timer("address_summary");
let rows = self
.history_iter_scan_reverse(code, hash)
.history_iter_scan_reverse(code, hash, start_height)
.map(TxHistoryRow::from_row);

self.collate_summaries(rows, last_seen_txid, limit)
Expand All @@ -672,14 +681,15 @@ impl ChainQuery {
&'a self,
scripthash: &[u8],
last_seen_txid: Option<&'a Txid>,
start_height: Option<u32>,
limit: usize,
) -> impl rayon::iter::ParallelIterator<Item = Result<(Transaction, BlockId)>> + 'a {
// scripthash lookup
self._history(b'H', scripthash, last_seen_txid, limit)
self._history(b'H', scripthash, last_seen_txid, start_height, limit)
}

pub fn history_txids_iter<'a>(&'a self, scripthash: &[u8]) -> impl Iterator<Item = Txid> + 'a {
self.history_iter_scan_reverse(b'H', scripthash)
self.history_iter_scan_reverse(b'H', scripthash, None)
.map(|row| TxHistoryRow::from_row(row).get_txid())
.unique()
}
Expand All @@ -689,12 +699,13 @@ impl ChainQuery {
code: u8,
hash: &[u8],
last_seen_txid: Option<&'a Txid>,
start_height: Option<u32>,
limit: usize,
) -> impl rayon::iter::ParallelIterator<Item = Result<(Transaction, BlockId)>> + 'a {
let _timer_scan = self.start_timer("history");

self.lookup_txns(
self.history_iter_scan_reverse(code, hash)
self.history_iter_scan_reverse(code, hash, start_height)
.map(|row| TxHistoryRow::from_row(row).get_txid())
// XXX: unique() requires keeping an in-memory list of all txids, can we avoid that?
.unique()
Expand Down Expand Up @@ -1208,7 +1219,13 @@ impl ChainQuery {
last_seen_txid: Option<&'a Txid>,
limit: usize,
) -> impl rayon::iter::ParallelIterator<Item = Result<(Transaction, BlockId)>> + 'a {
self._history(b'I', &asset_id.into_inner()[..], last_seen_txid, limit)
self._history(
b'I',
&asset_id.into_inner()[..],
last_seen_txid,
None,
limit,
)
}

#[cfg(feature = "liquid")]
Expand Down
91 changes: 58 additions & 33 deletions src/rest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -911,26 +911,31 @@ fn handle_request(

let mut txs = vec![];

if let Some(given_txid) = &after_txid {
let is_mempool = query
.mempool()
.history_txids_iter(&script_hash[..])
.any(|txid| given_txid == &txid);
let is_confirmed = if is_mempool {
false
} else {
query
.chain()
.history_txids_iter(&script_hash[..])
.any(|txid| given_txid == &txid)
};
if !is_mempool && !is_confirmed {
let after_txid_location = if let Some(txid) = &after_txid {
find_txid(txid, &query.mempool(), query.chain())
} else {
TxidLocation::Mempool
};

let confirmed_block_height = match after_txid_location {
TxidLocation::Mempool => {
txs.extend(
query
.mempool()
.history(&script_hash[..], after_txid.as_ref(), max_txs)
.into_iter()
.map(|tx| (tx, None)),
);
None
}
TxidLocation::None => {
return Err(HttpError(
StatusCode::UNPROCESSABLE_ENTITY,
String::from("after_txid not found"),
));
}
}
TxidLocation::Chain(height) => Some(height),
};

txs.extend(
query
Expand All @@ -951,7 +956,12 @@ fn handle_request(
txs.extend(
query
.chain()
.history(&script_hash[..], after_txid_ref, max_txs - txs.len())
.history(
&script_hash[..],
after_txid_ref,
confirmed_block_height,
max_txs - txs.len(),
)
.map(|res| res.map(|(tx, blockid)| (tx, Some(blockid))))
.collect::<Result<Vec<_>, _>>()?,
);
Expand Down Expand Up @@ -1008,8 +1018,7 @@ fn handle_request(
TxidLocation::Mempool
};

let mut confirmed_block_height = None;
match after_txid_location {
let confirmed_block_height = match after_txid_location {
TxidLocation::Mempool => {
txs.extend(
query
Expand All @@ -1018,17 +1027,16 @@ fn handle_request(
.into_iter()
.map(|tx| (tx, None)),
);
None
}
TxidLocation::None => {
return Err(HttpError(
StatusCode::UNPROCESSABLE_ENTITY,
String::from("after_txid not found"),
));
}
TxidLocation::Chain(height) => {
confirmed_block_height = Some(height);
}
}
TxidLocation::Chain(height) => Some(height),
};

if txs.len() < max_txs {
let after_txid_ref = if !txs.is_empty() {
Expand Down Expand Up @@ -1080,7 +1088,7 @@ fn handle_request(

let txs = query
.chain()
.history(&script_hash[..], last_seen_txid.as_ref(), max_txs)
.history(&script_hash[..], last_seen_txid.as_ref(), None, max_txs)
.map(|res| res.map(|(tx, blockid)| (tx, Some(blockid))))
.collect::<Result<Vec<_>, _>>()?;

Expand Down Expand Up @@ -1112,9 +1120,29 @@ fn handle_request(
.unwrap_or(config.rest_default_max_address_summary_txs),
);

let summary = query
.chain()
.summary(&script_hash[..], last_seen_txid.as_ref(), max_txs);
let last_seen_txid_location = if let Some(txid) = &last_seen_txid {
find_txid(txid, &query.mempool(), query.chain())
} else {
TxidLocation::Mempool
};

let confirmed_block_height = match last_seen_txid_location {
TxidLocation::Mempool => None,
TxidLocation::None => {
return Err(HttpError(
StatusCode::UNPROCESSABLE_ENTITY,
String::from("after_txid not found"),
));
}
TxidLocation::Chain(height) => Some(height),
};

let summary = query.chain().summary(
&script_hash[..],
last_seen_txid.as_ref(),
confirmed_block_height,
max_txs,
);

json_response(summary, TTL_SHORT)
}
Expand Down Expand Up @@ -1179,19 +1207,16 @@ fn handle_request(
TxidLocation::Mempool
};

let mut confirmed_block_height = None;
match last_seen_txid_location {
TxidLocation::Mempool => {}
let confirmed_block_height = match last_seen_txid_location {
TxidLocation::Mempool => None,
TxidLocation::None => {
return Err(HttpError(
StatusCode::UNPROCESSABLE_ENTITY,
String::from("after_txid not found"),
));
}
TxidLocation::Chain(height) => {
confirmed_block_height = Some(height);
}
}
TxidLocation::Chain(height) => Some(height),
};

let summary = query.chain().summary_group(
&script_hashes,
Expand Down

0 comments on commit b7d9b3a

Please sign in to comment.