Skip to content

draft: Better payment value distribution with rebalancing#311

Draft
carlaKC wants to merge 9 commits into
bitcoin-dev-project:mainfrom
carlaKC:payment-amounts-rebalance
Draft

draft: Better payment value distribution with rebalancing#311
carlaKC wants to merge 9 commits into
bitcoin-dev-project:mainfrom
carlaKC:payment-amounts-rebalance

Conversation

@carlaKC

@carlaKC carlaKC commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

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:

  • Check the math for payment amounts
  • We need to be able to exclude some channels from auto-rebalance

carlaKC and others added 9 commits July 7, 2026 13:23
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant