krabka_verified/quota/
refill.rs1use {super::quota_credit, creusot_std::prelude::*};
2
3#[requires(fraction@ < 1_000_000_000)]
10#[requires(available@ <= burst@ && (available@ == 0 || debt@ == 0))]
11#[ensures(result.0@ <= burst@ && (result.0@ == 0 || result.1@ == 0))]
12#[ensures(result.2@ < 1_000_000_000)]
13#[ensures({
14 let credit = (elapsed@ * rate@ + fraction@) / 1_000_000_000;
15 result.1@ == if credit <= debt@ { debt@ - credit } else { 0 }
16})]
17#[ensures({
18 let credit = (elapsed@ * rate@ + fraction@) / 1_000_000_000;
19 let paid = if credit <= debt@ { credit } else { debt@ };
20 result.0@ == crate::throttle::capped(available@, credit - paid, burst@)
21})]
22#[ensures(result.2@ == if result.0@ == burst@ && result.1@ == 0 { 0 }
23 else { (elapsed@ * rate@ + fraction@) % 1_000_000_000 })]
24#[ensures({
25 let balance = (available@ - debt@) * 1_000_000_000 + fraction@ + elapsed@ * rate@;
26 (result.0@ - result.1@) * 1_000_000_000 + result.2@
27 == if balance <= burst@ * 1_000_000_000 { balance } else { burst@ * 1_000_000_000 }
28})]
29#[must_use]
30pub fn quota_refill(
31 available: u64,
32 debt: u64,
33 fraction: u64,
34 elapsed: u64,
35 rate: u64,
36 burst: u64,
37) -> (u64, u64, u64) {
38 let numerator = u128::from(elapsed) * u128::from(rate) + u128::from(fraction);
39 let credit = numerator / 1_000_000_000;
40 let paid = credit.min(u128::from(debt)).min(18_446_744_073_709_551_615) as u64;
42 let excess = (credit - u128::from(paid))
43 .min(u128::from(burst))
44 .min(18_446_744_073_709_551_615) as u64;
45 let repaid = quota_credit(available, debt, paid, burst);
46 let filled = quota_credit(repaid.0, repaid.1, excess, burst);
47 let fraction = if filled.0 == burst && filled.1 == 0 {
48 0
49 } else {
50 (numerator % 1_000_000_000) as u64
51 };
52 (filled.0, filled.1, fraction)
53}