/** * Reorg detector — pure function over a recent-block ring. * * Per `docs/tx-tracker-spec.md` §12. The tracker keeps a small ring * of recently-observed canonical blocks (`BlockSample` below). On * every new tip, it walks the ring backward up to `reorgDepthBlocks` * (default 12) and asks: "is the canonical chain at any of those * heights different from what we recorded?" Any divergence becomes * a `vanished-from-block` candidate the tracker translates per * affected hash. * * Bounded depth (§12.2): a fixed 12-block window keeps the per-tick * work O(depth) regardless of how anomalous the upstream's history * is. Deeper reorgs are vanishingly rare on chains the package * targets; "find the common ancestor" would let one bad reorg make * a tick arbitrarily long. * * Pure: no I/O, no clock, no mutation of input. The tracker (in * `tracker.ts`) calls `appendBlock` to fold each newly-observed * canonical block into the ring, and `detectDivergences` against * a candidate canonical sequence (typically the source's most * recent emit + the on-demand block fetches the tracker did to * walk the chain backward). */ import type { Hash } from './events.js'; /** * One canonical-block coordinate the tracker has observed. The * tracker also records the `transactions` it saw on that block * (just the hashes, not the full RawTx) so it can quickly answer * "was tx X in block N?" without a fresh RPC. */ export interface BlockSample { number: bigint; hash: Hash; parentHash: Hash | null; /** Tx hashes observed in this block at the time it was canonical. */ transactionHashes: ReadonlySet; } /** * One divergence the detector found between the tracker's recorded * ring and a freshly-observed canonical chain. The tracker * translates this into per-hash `vanished-from-block` events for * every tracked hash whose `seen-in-block` referenced the previous * (now-stale) hash at this height. */ export interface BlockDivergence { blockNumber: bigint; /** Hash the ring previously had at this height. */ previousBlockHash: Hash; /** * Hash the canonical chain has at this height now. The detector * only emits divergences for heights where the caller passed an * explicit canonical block, so this is always a real hash. */ canonicalBlockHash: Hash; /** * Tx hashes the ring saw on the previously-canonical block at * this height. Tracker uses this to scope which tracked hashes * are affected. */ vanishedTransactionHashes: ReadonlySet; } /** * Append a freshly-observed canonical block into a bounded ring * keyed by block number, capped at `capacityBlocks` entries. Returns * a new ring (input is not mutated). The newest entry overwrites * any previous entry at the same number — a same-height reorg * replaces the stale block with the new canonical one. */ export declare const appendBlock: (ring: ReadonlyArray, block: BlockSample, capacityBlocks: number) => BlockSample[]; /** * Compare the tracker's `ring` (already-recorded canonical blocks) * against a freshly-observed `canonical` sequence (the tracker's * latest observation, plus any walk-back probes it performed). At * each height present in BOTH sides, if the hashes disagree the * detector returns a `BlockDivergence`. * * **Heights present only in `ring` are skipped** — the detector * treats "no canonical entry at this height" as "no information," * not "vanished." A real same-height reorg requires the caller to * explicitly pass the new canonical block at that height; gapping * (e.g. caller skipped a height) is not a divergence signal. * * If you need to detect "ring's tip is no longer in canonical" you * pass the canonical chain that explicitly covers that height; with * a partial canonical sequence the detector stays conservative. * * `depthBlocks` caps how far back the comparison runs. The tracker * rarely cares about divergences beyond `reorgDepthBlocks` because * any tracked tx that deep would already be considered finalized by * downstream consumer policy. * * Returns an empty array on a clean chain extension (no divergences). */ export declare const detectDivergences: (input: { ring: ReadonlyArray; canonical: ReadonlyArray; depthBlocks: number; }) => BlockDivergence[]; /** * Default reorg-detection depth in blocks. Conservative — even * Ethereum's worst recent reorgs are under 7 blocks, and unbounded * walks would let a single anomalous reorg make the tick arbitrarily * long (§12.2). Tunable per-tracker via * `CreateTxTrackerOptions.reorgDepthBlocks`. */ export declare const defaultReorgDepthBlocks = 12; //# sourceMappingURL=reorg.d.ts.map