draft: Better payment value distribution with rebalancing#311
Draft
carlaKC wants to merge 9 commits into
Draft
Conversation
The previous parametrization of the log normal distribution used for random payment amounts (mu = 2ln(amt) - ln(limit), sigma^2 = 2(ln(limit) - ln(amt))) technically had the expected payment amount as its mean, but with a pathologically heavy tail for realistic channel sizes: the median payment was amt^2 / limit (sub-satoshi dust for large channels) and exactly half of the distribution's expected volume sat above the payment limit itself, carried by astronomically rare payments that could never succeed. Sample means therefore never converged on the expected payment amount in practice, so nodes sent far less volume than their capacity and the simulation's activity multiplier implied. Re-parametrize with mu = ln(amt) - sigma^2/2, which has mean amt for any sigma, and choose sigma as large as possible subject to keeping 95% of samples below the payment limit and capping the coefficient of variation at one so that sample averages converge quickly (standard error of the mean is at most amt/sqrt(n) after n payments). The seeded end-to-end test's hard-coded payment ordering is regenerated because payment amount sampling shares the seeded rng stream with event timing; the test now asserts on a prefix of payments so that it does not depend on how many payments squeeze in at the wall-clock cutoff. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adds a primitive that resets a simulated channel's settled balance to an even split when either side's available liquidity has drawn down beneath a trigger fraction of capacity. This models the out-of-band actions that node operators use to restore usable liquidity (circular rebalances, swaps, splices) by their effect rather than their mechanism, so that long-running simulations can opt into sustained liquidity rather than permanent depletion. Balance locked in in-flight HTLCs is intentionally left untouched: only the settled portion of the channel is redistributed, which keeps the channel's capacity accounting invariant intact and lets in-flight HTLCs settle normally after a rebalance. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
No functional change. Ordering is needed so that tasks scanning the set of simulated channels can iterate in a stable order, keeping simulations run with a fixed seed deterministic. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adds SimGraph::start_rebalancer, which spawns a task that periodically scans the simulated network's channels and teleport-rebalances any channel whose available liquidity has drawn down beneath a configured fraction of its capacity. Without any restoring force, random payment activity progressively drains simulated channels to one side and payment success rates decay over long simulations. Real operators counteract this with out-of-band actions (circular rebalances, swaps, splices) that a payment-only simulator cannot express, so this task models their effect instead. It is opt-in: leaving it off remains the honest default for studying depletion behavior, while enabling it supports long-running load tests that need sustained liquidity. Each rebalance is logged with the amount moved, so the total intervention volume that a topology and traffic pattern require is itself observable output. The task introduces no new source of randomness to simulations run with a fixed seed: scans run at a fixed interval on the simulation clock and visit channels in short channel ID order. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adds an optional rebalance section to the simulation file that enables
periodic teleport-rebalancing of depleted channels on simulated
networks:
"rebalance": {
"trigger_below": 0.1,
"interval_secs": 3600
}
Both fields are optional and default to the values shown. The section
is rejected when running against real nodes, since the simulator has
no way to move liquidity in channels it does not control.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Pathfinding previously set no limit on total routing fees, so payments would route through channels advertising absurd fees when they offered the only (or best-scored) path. Some real-world graph exports use maxed-out fee rates to mark channel directions as unusable; with no budget, the simulator routes straight through them and the sender bleeds channel balance in fees. Because fees are not recorded in payment results, this drain is invisible in the simulation's output, surfacing only as mysterious liquidity depletion. Cap the fee budget at 5% of the payment amount, which is generous by real-node standards but prevents routing at any cost. Test payment amounts are increased so that their route fees fit within the new budget on the test networks' fee gradients. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Expose the maximum routing fee that simulated nodes will pay as a top-level max_route_fee_pct field in the simulation file, expressed as a percentage of the payment amount and defaulting to the previous hard-coded 5%. Experiments studying fee behavior may legitimately want a tighter or looser sender fee tolerance, so the budget becomes a knob rather than a constant. The percentage is threaded through ln_node_from_graph to each SimNode (validated to be positive), and find_payment_route now receives an explicit per-payment fee budget. As with rebalancing, the field is rejected for configurations that run against real nodes, which apply their own fee limits. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adds an exclusion list to RebalanceConfig so that individual nodes can opt out of the rebalancing task. A channel is skipped by scans if either of its peers is excluded, regardless of which side has drawn down, since a real channel cannot be rebalanced without the participation of the node that holds the depleted balance. This models operators that do not maintain their liquidity, and lets their channels drain naturally under the simulation's payment flows while the rest of the network is kept liquid. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adds an exclude list to the rebalance section of the simulation file,
containing the pubkeys of nodes that should not participate in
rebalancing:
"rebalance": {
"trigger_below": 0.1,
"interval_secs": 3600,
"exclude": ["02abc..."]
}
Exclusions that reference nodes that are not part of the simulated
network are rejected at startup, because they would otherwise be
silently ignored (most likely hiding a typo in the pubkey).
Co-Authored-By: Claude Fable 5 <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.
We know that the way that we generate traffic isn't great - see #301.
The former attempt at fixing this was abandoned because it caused simulations to un-balance, which was problematic for the long simulations we were running. A solution here is to allow an "arbitrary auto rebalance" in the network so that payments can keep flowing.
This is useful for the channel jamming case, because we just care about there being some activity that is reproducible across networks.
TBD: