Use time-paused tokio for zero sleeps#309
Open
carlaKC wants to merge 4 commits into
Open
Conversation
carlaKC
added a commit
to carlaKC/jam-ln
that referenced
this pull request
Jun 23, 2026
Switch from sim-ln's old wall-clock SimulationClock (a fixed u16 speedup that still slept on real time) to its reimplemented SimulationClock, which advances virtual time on a paused single-threaded runtime. A run now completes as fast as the CPU allows instead of sleeping on real time, and is reproducible for a fixed seed. Tracks bitcoin-dev-project/sim-ln#309. - Pin simln-lib/sim-cli to the PR head. - Drive all three binaries through runtime::block_on_sped_up_clock, which owns the paused runtime; main() is therefore synchronous. - Reimplement the local InstantClock trait on tokio::time::Instant so that elapsed time tracks virtual time (no ln-resource-mgr changes required). - Seed the latency interceptor from a shared SIM_SEED, matching sim-ln's seeded RNG. - Remove the obsolete --clock-speedup multiplier flag; SimulationClock no longer takes one. - Bound the run at one virtual year as a safeguard, since virtual time has no wall-clock limit if an attack never triggers shutdown. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
7e4eb94 to
bd2a169
Compare
Replace the wall-time multiplier SimulationClock (a u16 speedup capped at 1000x) and the separate SystemClock with a single SimulationClock that reports time relative to a SystemTime start anchor. now() is the start time plus a captured tokio::time::Instant's elapsed(), and sleep() defers to the tokio timer. How the speedup works: when this clock is driven on a paused tokio runtime (start_paused), the runtime freezes the Instant clock and, once no task is runnable, auto-advances it to the nearest pending timer. So sleep() resolves with no real time elapsed and now() jumps straight to the next scheduled event, letting a simulation run as fast as the CPU allows while staying reproducible. On a regular (non-paused) runtime the exact same clock simply tracks real time relative to its start, which is how real-node runs use it. The paused runtime needs tokio's test-util at runtime, so it is gated behind the new opt-in `virtual-time` feature rather than always compiled in. Tests construct the clock with SystemTime::now() (live time) rather than a fixed epoch: LDK's network-graph gossip validation checks channel_update timestamps against the real wall clock and rejects anything older than two weeks, so a hardcoded past start time makes populate_network_graph fail. This commit only lands the clock itself. The runtime helper that drives it on a paused runtime and the CLI opt-in are removed here for the sake of atomic commits and reintroduced in later commits; the old --speedup-clock flag and its validation are dropped accordingly, so for now every run tracks real time. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Running a simulation on virtual time needs a single-threaded, time-paused runtime: single threaded so scheduling is deterministic, paused so virtual time auto-advances to the next timer instead of waiting on the wall clock. Leaving callers to set this up invites silently losing determinism or the virtual-time advance. Add runtime::block_on_virtual_time, which owns that runtime, constructs a SimulationClock on it, and runs a caller-provided build-and-run closure to completion. It rejects being called from within an existing runtime (returning the new SimulationError::RuntimeError) rather than panicking on a nested block_on. The module is gated behind the virtual-time feature. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Nothing in the parse_sim_params call stack actually awaits: it only does blocking std::fs reads and a blocking dialoguer prompt. Drop the vestigial async/await from parse_sim_params, read_sim_path and select_sim_file. This is preparation for the following commit, which runs the simulation on a paused virtual-time runtime. There, main() becomes a plain sync fn that picks a runtime only after parsing, so parsing must not require an async context of its own. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
carlaKC
added a commit
to carlaKC/jam-ln
that referenced
this pull request
Jun 25, 2026
Switch from sim-ln's old wall-clock SimulationClock (a fixed u16 speedup that still slept on real time) to its reimplemented SimulationClock, which advances virtual time on a paused single-threaded runtime. A run now completes as fast as the CPU allows instead of sleeping on real time, and is reproducible for a fixed seed. Tracks bitcoin-dev-project/sim-ln#309. - Pin simln-lib/sim-cli to the PR head, enabling simln-lib's virtual-time feature (required for runtime::block_on_virtual_time, which pulls in tokio's test-util to drive the paused runtime). - Drive all three binaries through runtime::block_on_virtual_time, which owns the paused runtime; main() is therefore synchronous. - Reimplement the local InstantClock trait on tokio::time::Instant so that elapsed time tracks virtual time (no ln-resource-mgr changes required). - Seed the simulation config and latency interceptor from a shared SIM_SEED so that payment generation and sampled delays are reproducible. - Remove the obsolete --clock-speedup multiplier flag; SimulationClock no longer takes one. - Bound the run at one virtual year as a safeguard, since virtual time has no wall-clock limit if an attack never triggers shutdown. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add --virtual-time, an opt-in flag for simulated networks. When set, the simulation runs on the library's paused single-threaded runtime, so virtual time advances instantly to the next event: a multi-day run finishes in seconds and is reproducible for a given seed. When absent, the simulation runs on a regular multi-threaded runtime in real time, as before. main parses and validates the simulation params once up front, then selects the runtime by the flag: virtual-time runs go through block_on_virtual_time (which owns the paused runtime and hands back a SimulationClock); regular runs use a standard runtime. The flag is validated to require a simulated network and --total-time (an unbounded run would otherwise advance virtual time forever). sim-cli enables simln-lib's virtual-time feature so the flag is always available. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
carlaKC
added a commit
to carlaKC/jam-ln
that referenced
this pull request
Jun 26, 2026
Move off sim-ln's old wall-clock SimulationClock (a fixed speedup multiplier that still slept on real time) onto its reimplemented virtual-time SimulationClock, which advances time on a paused single-threaded runtime so a run completes as fast as the CPU allows. - Pin simln-lib/sim-cli to the virtual-time PR head and enable simln-lib's virtual-time feature, which provides runtime::block_on_virtual_time. - Drive all three binaries through block_on_virtual_time, which owns the paused runtime and hands the simulation its clock; main() is therefore synchronous. - Adopt the new SimulationClock::new(start_time) constructor in place of the speedup-multiplier form across the binaries, tests and graph setup. - Reimplement the local InstantClock trait on tokio::time::Instant so that elapsed time tracks virtual time. - Pass None to the latency interceptor's new seed parameter for now; seeding follows in a later commit. Tracks bitcoin-dev-project/sim-ln#309. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Our current solution to waits is to use a sped up wall clock, which has all sorts of limitations.
Using a paused, single-threaded tokio runtime we can get discrete-event-like functionality without doing a large refactor.