19ba4e3d67516e4a3045b9870ccf7bfd6173579e fix(esplora): stop paging when the server does not advance the cursor (luhrhenz)
Pull request description:
### Description
Fixes #2339.
`bdk_esplora` pages each script pubkey's history by passing the previous page's last txid as the cursor, and stops only on a page of fewer than 25 txs. A server that ignores the cursor returns the same full page forever, so `sync`/`full_scan` never returns and memory grows without bound.
The loop now records every cursor it pages from and returns `InvalidResponse` when a full page ends on one it has already seen. This catches both a repeated page and a cycle (`A -> B -> A`). Applied to both `async_ext.rs` and `blocking_ext.rs`.
### Notes to the reviewers
- It returns an error rather than `break`ing, so that `sync` never reports a truncated history as success.
- There is no page cap, so long histories aren't truncated. A correct server never repeats a cursor, so the check can't trigger on one.
- The regression tests use a small `TcpListener` stub in `tests/common` that always returns the same page, since `TestEnv` can't fake a misbehaving server. `tokio`'s `time` dev-dep feature is for the async test's timeout.
### Changelog notice
- Fixed `bdk_esplora`'s pagination loop hanging when a chain source returns a page that does not advance the `last_seen` cursor.
### Checklists
#### All Submissions:
* [x] I followed the [contribution guidelines](https://github.com/bitcoindevkit/bdk/blob/master/CONTRIBUTING.md)
* [x] I ran `cargo fmt` and `cargo clippy` before committing
#### Bugfixes:
* [ ] This pull request breaks the existing API
* [x] I've added tests to reproduce the issue which are now passing
* [x] I'm linking the issue being fixed by this PR
ACKs for top commit:
evanlinjin:
ACK
19ba4e3d67516e4a3045b9870ccf7bfd6173579e
Tree-SHA512: c67af0009ad6e84cf13d681aedcb4bf241bc22199d7cf32c76d0f0e2559bdc01253856523262f7016f31d1ae0b834bd1a4fc4a513232fe22b827d507da4b538d