fn start_protocol_channel_capacity(cfg: &SessionManagerConfig) -> usizeExpand description
Capacity of the Start protocol ingress channel.
This channel is fed by SessionManager::dispatch_message with try_send, and an overflow
drops the message. For most Start messages that is recoverable, but a dropped SsaCommit
is not: there is no NACK or retransmission, so the corresponding coefficient cell stays empty
forever, the commitment never completes, every subsequent share fails to verify, and the cycle
dies on the deposit kill switch.
PIX changed this channel’s load from roughly one message per session to the entire commitment
set of an SSA cycle, chunked into packet-sized messages, plus a reserve for ordinary Start
traffic. Batching multiplies that: an Exit that asks for
ssas_per_request SSAs at once gets that many
cycles’ commitment sets back-to-back, all landing here, so the per-cycle term is scaled by it.
The per-cycle burst is bounded by two independent limits, and the capacity takes the smaller:
quota_range.end() / PAYLOAD_SIZEispolys × (threshold + surplus), an over-estimate by that whole second factor, since a cycle carries one constant term per polynomial and nothing else. The quota alone does not reveal how the product splits, so the over-estimate cannot be undone from it.MAX_POLYS_PER_SSAis the number of polynomialsSessionManager::check_pix_paramswill accept, whatever the quota says. It therefore bounds the commitments a cycle can ever deliver.
Clamping to the second matters because this capacity is reserved, not merely enforced:
crossfire’s array flavour pre-allocates every slot when the channel is built. An
operator-settable quota_range feeding an unclamped derivation is an allocation with no upper
bound — at quota_range.end() = 1e13 it asks for 77 GB. Over-provisioning is still the safe
direction within the clamp, and the surviving margin is large: the default dimensions burst
≈ 320 messages against a capacity term of ≈ 648.
The batch factor is bounded by MAX_SSA_BATCH_SIZE for the same allocation reason, and is
clamped here rather than being taken on trust from the config, so that callers which build a
SessionManagerConfig without going through SessionManager::new cannot inflate it.
The session term is clamped for the same reason. maximum_managed_sessions validates up to
100 000, and one slot holds a (HoprPseudonym, HoprStartProtocol) sized by the enum’s largest
variant, so an operator raising the session limit would silently buy a multi-megabyte startup
allocation. Ordinary Start traffic is one message per session in flight, not one per session
the node will ever manage, so MAX_CONCURRENT_START_EXCHANGES is the honest bound.