1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
//! Rate enforcement for incremental voucher payments.
//!
//! Each voucher carries cumulative `amount` and `bytes_delivered`. Between
//! two vouchers on the same lane, the increments must satisfy
//! `amount_delta / bytes_delta >= rate_per_mb` — i.e. the client paid at
//! least the advertised rate for the bytes delivered. Underpayment beyond a
//! tolerance threshold (rounding error, edge-MB padding) indicates a faulty
//! or hostile client.
//!
//! Rate units, all matching ADR 005 / ADR 003:
//! - `amount` is in token base units (`µUSDC` = 10⁻⁶ `USDC`)
//! - `bytes_delivered` is in bytes
//! - `rate_per_mb` is in token base units per **megabyte**, where 1 `MB` =
//! 1,048,576 bytes (binary `MB`, ADR 005)
//!
//! Tolerance is expressed in basis points (bps); 100 bps = 1%. The default
//! [`DEFAULT_TOLERANCE_BPS`] of 100 leaves headroom for the rounding the
//! client does when computing `amount = ceil(bytes / 1_048_576) * rate`.
use U256;
/// 1 `MB` in bytes per ADR 005 §Probe-Triggered Eviction Hold's `MB`
/// definition.
pub const BYTES_PER_MB: u64 = 1_048_576;
/// Basis-points scale: 100% = `10_000` `bps`.
pub const BPS_SCALE: u64 = 10_000;
/// Default underpayment tolerance — 1%. Calibrated against the client-side
/// rounding `amount = ceil(bytes / 1_048_576) * rate_per_mb`: at 1 MB
/// granularity the worst-case underpayment is < 1 byte's-worth of rate, so
/// 100 bps leaves >>10× headroom.
pub const DEFAULT_TOLERANCE_BPS: u64 = 100;
/// Verify that paying `amount_delta` for `bytes_delta` bytes meets
/// `rate_per_mb` within `tolerance_bps`.
///
/// # Errors
///
/// - [`RateError::ZeroBytes`] — `bytes_delta == 0`. A voucher that adds no
/// bytes cannot be priced and is silently invalid.
/// - [`RateError::Underpayment`] — effective rate is below `rate_per_mb` by
/// more than `tolerance_bps` basis points.
/// - [`RateError::Overflow`] — `amount_delta * BYTES_PER_MB * BPS_SCALE`
/// would exceed `U256::MAX`. Will not occur in practice (would require
/// ~10⁶³ `µUSDC`, far more than total `USDC` supply).
/// Minimum payment (in token base units) required to cover `bytes` delivered
/// at `rate_per_mb`, i.e. `ceil(bytes * rate_per_mb / BYTES_PER_MB)`.
///
/// This is the exact lower bound [`verify_rate`] enforces at zero tolerance and
/// the same arithmetic the buyer's voucher signer uses to price an interval
/// (`bytes * rate / MB`, rounded up). It is intended for pre-flight cost
/// estimation — e.g. gating a speculative pull on the requesting lane's
/// remaining deposit covering the worst-case blob cost (#856).
///
/// Saturating on the (practically unreachable) multiply overflow: a saturated
/// `U256::MAX` ceiling makes any finite deposit look insufficient, which is the
/// safe, conservative direction for a guard.
/// Stateful-B pool solvency: the pool's remaining deposit minus the refundable
/// floor `M` must cover its already-committed concurrent floor credit plus this
/// stream's new reservation. Saturating (a `remaining` below `M` yields no
/// headroom rather than underflowing).
/// Failure modes for [`verify_rate`].