Skip to content

feat: buy a member's shortfall with its top-up after an outage allowance is removed - #80

Draft
timwu20 wants to merge 3 commits into
feat/outage-traffic-allowancefrom
feat/outage-allowance-settlement
Draft

timwu20 wants to merge 3 commits into
feat/outage-traffic-allowancefrom
feat/outage-allowance-settlement

Conversation

@timwu20

@timwu20 timwu20 commented Oct 14, 2026 •

Copy link
Copy Markdown
Collaborator

Stacked on #71, which lets a dedicated synchronizer's operator set an outage traffic allowance. This handles what happens once the operator removes it, split out of #71 in review.

A member that used the allowance is below zero once it's removed, and the sequencer refuses it until its purchases cover what it consumed.

  • Shortfall with the top-up. When a member's remainder is below zero, the validator's top-up buys that shortfall together with the configured top-up in one purchase, and the funds check prices both: minWalletBalanceForTopup takes the extra traffic as a parameter. Before, it bought one top-up per minTopupInterval and left the member blocked for several intervals.
  • Fallback. If the wallet doesn't cover both, it buys the top-up alone, which still pays the shortfall down one interval at a time. It warns when that leaves the member below zero, and logs at info when the top-up alone covers the shortfall.
  • Not buying it twice. The member's traffic state only shows a purchase once the operator grants it. So the validator remembers, in memory, the traffic-state serial its last shortfall purchase was made at, and buys the top-up alone while that serial is unchanged. Any traffic update ends this, as does a restart, so a shortfall can occasionally be bought early; the traffic is kept.
  • Budget. The budget goes first to purchases that leave their member able to submit, then to those fallbacks with what's left, so a fallback can't starve another synchronizer's top-up.
  • Warnings. When even the top-up alone doesn't fit, the insufficient-funds warning names both amounts.

With no shortfall, the top-up behaves exactly as before. The shortfall bought isn't capped, so it's bounded by the allowance the operator set. The top-up docs (traffic_topups.rst) and ValidatorAppConfig comments describe it.

Tests.

  • SyncOperatorTrafficIntegrationTest continues feat: let the sync operator set an outage traffic allowance #71's outage flow past the removal: bob is refused, then one top-up buys exactly his shortfall (27.5 KB) together with his top-up (12 KB, derived from his config), and he transacts again. It checks the shortfall is larger than the top-up, and that bob's participant sees the same remainder as the sequencer.
  • The test environment is DevNet, where the wallet doesn't bound purchases, so the fallback and the two-pass budget are covered by unit tests only, as is the decision whether to hold the shortfall.
  • Unit tests for the shortfall, the hold, the two-pass budget allocation and the pricing.

Closes ChainSafe/canton-extending-mainnet#129, together with #71.

@timwu20
timwu20 force-pushed the feat/outage-allowance-settlement branch from f46d2aa to 317d444 Compare October 14, 2026 13:54
@timwu20
timwu20 force-pushed the feat/outage-traffic-allowance branch from 88e43a6 to 6f76e28 Compare October 14, 2026 13:54
@timwu20
timwu20 force-pushed the feat/outage-allowance-settlement branch from 317d444 to 570d366 Compare October 14, 2026 17:09
…nce is removed [ci]

Once a dedicated synchronizer's operator removes an outage traffic
allowance a member used, the member is below zero and refused until its
purchases cover what it consumed. The validator's top-up now buys that
shortfall together with the configured top-up in one purchase, and the
funds check prices both. Before, it bought one top-up per
minTopupInterval and left the member blocked for several intervals.

If the wallet does not cover both, it buys the top-up alone, which still
pays the shortfall down, and warns. The budget goes first to purchases
that leave their member able to submit, then to such fallbacks, so a
fallback cannot starve another target's top-up. When even the top-up
alone does not fit, the insufficient-funds warning names both amounts.

The integration test now continues past the removal: bob is refused,
then one top-up buys exactly his shortfall with the configured top-up,
and he transacts again.

Signed-off-by: Timothy Wu <tim.wu@chainsafe.io>
- Don't buy a member's shortfall again while the last shortfall
  purchase for that synchronizer hasn't been granted: until the
  member's traffic-state serial moves, the top-up is bought alone. The
  record is kept in memory, so after a restart a pending shortfall can
  be bought once more.
- The insufficient-funds warning names the top-up plus the shortfall
  only when the top-up alone wouldn't take the member above zero, and
  computes it from the configured top-up. The fallback warning says
  the top-up alone will be bought.
- unblocks is described as what it checks, and the fundedTasks
  parameter no longer shadows it.
- The integration test derives bob's top-up from his config, checks
  the shortfall is larger than it, and that bob's participant sees the
  same remainder as the sequencer before his top-up resumes.
- The top-up docs and ValidatorAppConfig comments mention the
  shortfall.

Signed-off-by: Timothy Wu <tim.wu@chainsafe.io>
… [ci]

The fallback message is a warning only when the top-up alone leaves the
member below zero; when it covers the shortfall, the member can submit
all the same and it is logged at info. The hold's comments say that
any traffic update ends it, also a grant of another purchase while ours
is pending, and that a restart or an unseen purchase outcome does too;
the remaining shortfall is then bought again early, not lost. The
allocation doc covers a top-up bought alone while a shortfall purchase
is pending, and the docs say what an outage traffic allowance is.

Signed-off-by: Timothy Wu <tim.wu@chainsafe.io>
@timwu20
timwu20 force-pushed the feat/outage-allowance-settlement branch from 570d366 to 98a0ebb Compare October 14, 2026 17:17

This branch has not been deployed

No deployments
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