Context
Bee master, package pkg/settlement/pseudosettle. This is a code-level accounting correctness issue found by reading the settlement logic; it is not environment specific.
Summary
The time-based allowance granted for an incoming refreshment is computed as (now - lastSettlementTime) * refreshRate. On first contact with a peer there is no stored settlement record, so lastSettlementTime defaults to 0 (the Unix epoch), making the allowance now * refreshRate, i.e. the entire Unix epoch scaled by the refresh rate.
Expected behavior
The time-based allowance should reflect the time elapsed since the peer connected, so the first refreshment forgives only the debt accrued over the elapsed connected time.
Actual behavior
The first refreshment from a peer can forgive an effectively unbounded debt (bounded only by the peer's current debt), independent of how long the peer has actually been connected, because the allowance window starts at the Unix epoch rather than the connection time.
Steps to reproduce
- Connect a peer and let it accrue debt.
- Have the peer send its first pseudosettle refreshment.
- Observe that
peerAllowance returns min(debt, now*refreshRate) and the full debt is accepted regardless of connection duration, because lastTime.Timestamp defaults to 0 on storage.ErrNotFound in peerAllowance (pkg/settlement/pseudosettle/pseudosettle.go).
Possible solution
Record the connection time per peer in init and anchor the first-contact allowance to it rather than to the epoch, so the initial refreshment only forgives debt accrued over the elapsed connected time. Subsequent settlements are unchanged.
AI Disclosure
Context
Bee
master, packagepkg/settlement/pseudosettle. This is a code-level accounting correctness issue found by reading the settlement logic; it is not environment specific.Summary
The time-based allowance granted for an incoming refreshment is computed as
(now - lastSettlementTime) * refreshRate. On first contact with a peer there is no stored settlement record, solastSettlementTimedefaults to0(the Unix epoch), making the allowancenow * refreshRate, i.e. the entire Unix epoch scaled by the refresh rate.Expected behavior
The time-based allowance should reflect the time elapsed since the peer connected, so the first refreshment forgives only the debt accrued over the elapsed connected time.
Actual behavior
The first refreshment from a peer can forgive an effectively unbounded debt (bounded only by the peer's current debt), independent of how long the peer has actually been connected, because the allowance window starts at the Unix epoch rather than the connection time.
Steps to reproduce
peerAllowancereturnsmin(debt, now*refreshRate)and the full debt is accepted regardless of connection duration, becauselastTime.Timestampdefaults to0onstorage.ErrNotFoundinpeerAllowance(pkg/settlement/pseudosettle/pseudosettle.go).Possible solution
Record the connection time per peer in
initand anchor the first-contact allowance to it rather than to the epoch, so the initial refreshment only forgives debt accrued over the elapsed connected time. Subsequent settlements are unchanged.AI Disclosure