You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
refactor(storage): enforce API limits via stackable guard layer (#1630)
Replace the transactions-only WithMax* opts with a single, stackable guard
decorator layer applied service-wide at the multiplexed driver seam, addressing
review feedback that the per-constructor opts approach did not scale.
- New token/services/storage/db/guard package: Policy (loaded once from
token.storage.maxPayloadSize / maxPageSize), payload-size checks, a
row-capping LimitIterator, and interface-embedding decorators for the
transaction, token, endorser, identity, and wallet stores.
- multiplexed.Driver wraps each NewXxx result with the guard, so every backing
driver (sqlite, postgres) and store is covered by one mechanism.
- Remove the maxPayloadSize/maxPageSize fields, WithMax* options and inline
checks from the SQL transaction store and its config/driver wiring.
- pagination.ValidateLimited now also caps keyset page size and guards a
typed-nil offset.
- Writes (payload size) and streaming/paginated reads (row cap) are guarded;
QueryMovements stays uncapped (balance totals). Materialized slice/map reads
are a tracked follow-up.
- Update storage/configuration docs to describe the service-wide limits.
Signed-off-by: AkramBitar <akram@il.ibm.com>
Copy file name to clipboardExpand all lines: docs/services/storage.md
+47-25Lines changed: 47 additions & 25 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -315,28 +315,50 @@ Cleanup behavior is controlled by the configuration section. See the [Configurat
315
315
316
316
See the [Configuration Guide](../configuration.md), Section `Optional: token.tms.<name>.services.network.fabric.recovery`, for detailed parameter descriptions and tuning recommendations.
317
317
318
-
## Transaction Store API Limits
319
-
320
-
The transaction store (used by both **TTXDB** and **AuditDB**) limits its writes and
321
-
reads so one huge write or one runaway query can't eat up the database. The checks
322
-
live in the single SQL implementation
323
-
(`token/services/storage/db/sql/common/transactions.go`), so the owner and auditor
324
-
stores are both covered.
325
-
326
-
**Write size limit.** `AddTokenRequest`, `AddTransaction`, and `AddMovement` reject a
327
-
call whose payload is larger than `maxPayloadSize` (default 4 MiB; `0` turns the check
328
-
off). `AddTokenRequest` measures the raw token request plus its metadata;
329
-
transaction and movement records add up their field lengths instead, to keep the
330
-
write path fast.
331
-
332
-
**Read size limits.** `QueryTransactions` needs a page with a size limit (`nil` and
333
-
`pagination.None()`are rejected; callers page through the full result set).
334
-
`QueryTokenRequests`adds a hard `LIMIT` equal to `maxPageSize` (default 1000).
335
-
`QueryMovements` is left uncapped on purpose: it feeds balance totals, and dropping
336
-
rows there would quietly return wrong balances. It is already narrowed by its required
337
-
filters.
338
-
339
-
Both limits have built-in defaults. You can override them in configuration
340
-
(`token.storage.maxPayloadSize` / `maxPageSize`) or in code with the
341
-
`WithMaxPayloadSize`/ `WithMaxPageSize` store options. See the
342
-
[Configuration Guide](../configuration.md) for the config keys.
318
+
## Storage API Limits
319
+
320
+
The storage service limits its writes and reads so one huge write or one runaway
321
+
query can't exhaust the database (issue #1630, CWE-400 / CWE-770). The limits are
322
+
enforced by a single, stackable **guard** decorator layer
323
+
(`token/services/storage/db/guard/`) applied once at the multiplexed driver
324
+
(`token/services/storage/db/multiplexed/driver.go`) as each store is created, so
325
+
every backing driver (SQLite, PostgreSQL) and every store is covered by the same
326
+
mechanism. The decorators embed the store interfaces and override only the methods
327
+
that need a check, delegating everything else — new layers (metrics, tracing) can be
328
+
stacked the same way, with the concrete SQL store at the bottom.
329
+
330
+
A single `Policy` (`MaxPayloadSize`, `MaxPageSize`) drives every check. It is loaded
331
+
once from configuration; absent keys fall back to the built-in defaults, and an
0 commit comments