Skip to content

Commit 98ae002

Browse files
fix: continue address tx pagination across mempool boundary
The address tx history endpoints could stop pagination at the mempool/chain boundary when after_txid pointed to the last mempool transaction for an address or address group. The confirmed-history query was reusing after_txid whenever the mempool query returned no rows, even if that cursor only existed in mempool. This change makes the confirmed-history query reuse after_txid only when the cursor was actually found in chain history; mempool cursors now correctly fall through to the newest confirmed transactions. Co-authored-by: Saravanan Mani <228955468+saravanan7mani7@users.noreply.github.com>
1 parent 3d8d6e6 commit 98ae002

1 file changed

Lines changed: 50 additions & 14 deletions

File tree

src/rest.rs

Lines changed: 50 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -583,6 +583,19 @@ fn find_txid(
583583
}
584584
}
585585

586+
#[inline]
587+
fn confirmed_after_txid<'a>(
588+
after_txid_location: &TxidLocation,
589+
after_txid: Option<&'a Txid>,
590+
) -> Option<&'a Txid> {
591+
match after_txid_location {
592+
// A mempool cursor never exists in chain history, so always
593+
// start from the newest confirmed tx when crossing the boundary.
594+
TxidLocation::Mempool | TxidLocation::None => None,
595+
TxidLocation::Chain(_) => after_txid,
596+
}
597+
}
598+
586599
/// Prepare transactions to be serialized in a JSON response
587600
///
588601
/// Any transactions with missing prevouts will be filtered out of the response, rather than returned with incorrect data.
@@ -960,13 +973,8 @@ fn handle_request(
960973
};
961974

962975
if txs.len() < max_txs {
963-
let after_txid_ref = if !txs.is_empty() {
964-
// If there are any txs, we know mempool found the
965-
// after_txid IF it exists... so always return None.
966-
None
967-
} else {
968-
after_txid.as_ref()
969-
};
976+
let after_txid_ref =
977+
confirmed_after_txid(&after_txid_location, after_txid.as_ref());
970978
let mut confirmed_txs = query
971979
.chain()
972980
.history(
@@ -1067,13 +1075,8 @@ fn handle_request(
10671075
};
10681076

10691077
if txs.len() < max_txs {
1070-
let after_txid_ref = if !txs.is_empty() {
1071-
// If there are any txs, we know mempool found the
1072-
// after_txid IF it exists... so always return None.
1073-
None
1074-
} else {
1075-
after_txid.as_ref()
1076-
};
1078+
let after_txid_ref =
1079+
confirmed_after_txid(&after_txid_location, after_txid.as_ref());
10771080
let mut confirmed_txs = query
10781081
.chain()
10791082
.history_group(
@@ -2148,6 +2151,8 @@ impl From<address::AddressError> for HttpError {
21482151

21492152
#[cfg(test)]
21502153
mod tests {
2154+
use super::{confirmed_after_txid, TxidLocation};
2155+
use crate::chain::Txid;
21512156
use crate::rest::HttpError;
21522157
use serde_json::Value;
21532158
use std::collections::HashMap;
@@ -2214,6 +2219,37 @@ mod tests {
22142219
assert!(err.is_err());
22152220
}
22162221

2222+
#[test]
2223+
fn test_confirmed_after_txid_uses_chain_cursor_only() {
2224+
let txid: Txid = "0000000000000000000000000000000000000000000000000000000000000001"
2225+
.parse()
2226+
.unwrap();
2227+
2228+
assert_eq!(
2229+
confirmed_after_txid(&TxidLocation::Mempool, Some(&txid)),
2230+
None
2231+
);
2232+
assert_eq!(confirmed_after_txid(&TxidLocation::None, Some(&txid)), None);
2233+
assert_eq!(
2234+
confirmed_after_txid(&TxidLocation::Chain(123), Some(&txid)),
2235+
Some(&txid)
2236+
);
2237+
}
2238+
2239+
#[test]
2240+
fn test_confirmed_after_txid_allows_mempool_chain_boundary_progress() {
2241+
let txid: Txid = "0000000000000000000000000000000000000000000000000000000000000002"
2242+
.parse()
2243+
.unwrap();
2244+
2245+
// If a mempool cursor returns no newer mempool txs, confirmed history
2246+
// must start from the newest confirmed tx instead of seeking this txid.
2247+
assert_eq!(
2248+
confirmed_after_txid(&TxidLocation::Mempool, Some(&txid)),
2249+
None
2250+
);
2251+
}
2252+
22172253
#[test]
22182254
fn test_difficulty_new() {
22192255
use super::difficulty_new;

0 commit comments

Comments
 (0)