# API-004: No Storage Access

> **Authoritative requirement:** [API-004](../NORMATIVE.md#API-004)
> **Verification:** [VERIFICATION.md](../VERIFICATION.md)
> **Tracking:** [TRACKING.yaml](../TRACKING.yaml)
> **Spec reference:** [SPEC.md](../../../../resources/SPEC.md) — Sections 1, 3.1, 5.1

---

## Summary

`dig-clvm` MUST NOT perform any database lookups, network requests, or filesystem access. All external state required for validation -- coin records, block heights, timestamps, network constants -- MUST be passed in via function parameters. This is a hard architectural boundary that ensures the crate remains a pure computation library.

This design mirrors Chia L1's separation of concerns. On L1, the Rust consensus code (`chia_rs`) receives all necessary data through function parameters from the Python orchestration layer. The coin store is queried in Python ([`mempool_manager.py:480`](https://github.com/Chia-Network/chia-blockchain/blob/main/chia/full_node/mempool_manager.py#L480)), and the results are passed into Rust functions like `run_spendbundle()` and `validate_clvm_and_signature()`. DIG follows the same pattern: the caller loads coin records from its database and passes them into `validate_spend_bundle()` via `ValidationContext`.

This constraint is complementary to [API-002](API-002.md) (no async/IO dependencies) but goes further: even if a synchronous file read or database query were possible without banned dependencies, it would still violate this requirement. The crate's functions are pure: given the same inputs, they always produce the same outputs, with no hidden dependencies on external state.

---

## Specification

### Prohibited Operations

The following categories of operations MUST NOT appear anywhere in `dig-clvm/src/`:

| Category | Examples | Reason |
|---|---|---|
| Database access | RocksDB, SQLite, sled, any key-value store | Storage is caller's responsibility |
| Filesystem access | `std::fs::*`, `std::io::*` (for file ops), `std::path::Path` reads | Crate has no filesystem context |
| Network access | TCP/UDP sockets, HTTP requests, RPC calls | Pure computation, no I/O |
| Environment variables | `std::env::var()` | Configuration is passed via parameters |
| Global mutable state | `static mut`, `lazy_static` with side effects | Functions must be deterministic |

### Required Parameter-Passing Pattern

All external state MUST be provided through function parameters:

```rust
// CORRECT: All state passed in
pub fn validate_spend_bundle(
    bundle: &SpendBundle,          // The spend bundle to validate
    context: &ValidationContext,    // Chain state (height, coins, constants)
    config: &ValidationConfig,     // Validation parameters (cost limits, flags)
    bls_cache: Option<&mut BlsCache>,  // Optional signature cache
) -> Result<SpendResult, ValidationError>;

// The caller loads coin records from their database:
pub struct ValidationContext {
    pub height: u32,
    pub timestamp: u64,
    pub constants: NetworkConstants,
    pub coin_records: HashMap<Bytes32, CoinRecord>,  // Caller provides these
    pub ephemeral_coins: HashSet<Bytes32>,
}
```

```rust
// WRONG: Internal database lookup (hypothetical, must never exist)
pub fn validate_spend_bundle(bundle: &SpendBundle) -> Result<SpendResult, ValidationError> {
    let coins = DATABASE.get_coins(...);  // VIOLATION
}
```

### Allowed std Usage

The following `std` modules ARE permitted because they are pure computation:

- `std::collections` (HashMap, HashSet, Vec, etc.)
- `std::fmt` (Display, Debug formatting)
- `std::error` (Error trait)
- `std::convert` (From, Into)
- `std::ops` (operator traits)
- `std::mem`, `std::ptr` (memory management, no I/O)

---

## Acceptance Criteria

- [ ] No source file in `dig-clvm/src/` uses `std::fs`, `std::net`, or `std::io` for I/O operations
- [ ] No source file accesses environment variables via `std::env::var`
- [ ] All public functions accept external state as parameters, not fetched internally
- [ ] `ValidationContext` requires the caller to supply `coin_records` -- the crate never queries a coin database
- [ ] No global mutable state (`static mut`, `lazy_static` with I/O) exists in the crate
- [ ] The crate compiles and runs correctly in environments without filesystem or network access (e.g., WASM)

---

## Implementation Notes

- `std::io::Error` may appear in trait bounds or error types that wrap upstream errors. This is acceptable as long as no actual I/O operations are performed.
- The `BlsCache` parameter demonstrates the pattern: rather than maintaining a global cache internally, the caller owns the cache and passes a mutable reference. This gives callers control over cache lifetime and sharing across validation calls.
- `HashMap` and `HashSet` in `ValidationContext` use the standard library's hash implementations, which is acceptable -- they are in-memory data structures, not storage.
- Future extensions (e.g., loading puzzle reveals from a puzzle database) MUST follow the same pattern: the caller provides the data, the crate computes on it.

---

## Verification

### Test Plan

1. **Source code scan for I/O operations**:
   ```bash
   grep -rn "std::fs\|std::net\|std::io::Read\|std::io::Write\|std::io::BufRead" dig-clvm/src/
   grep -rn "std::env::var\|std::env::args" dig-clvm/src/
   grep -rn "static mut\|lazy_static" dig-clvm/src/
   ```
   - All three commands MUST produce no output.

2. **API surface review**:
   - Examine every `pub fn` in the crate. Each must accept all required external state as parameters.
   - No function signature should imply hidden state access (e.g., no `fn validate()` with no parameters that somehow knows about coins).

3. **Determinism test**:
   - Call `validate_spend_bundle()` twice with identical inputs. Both calls MUST produce identical outputs.
   - This confirms no hidden mutable state or external I/O affects results.

4. **Negative test**:
   - Attempt to introduce a `std::fs::read()` call in a test branch and verify that code review / CI would catch it.

---

## Source Citations

- [SPEC.md Section 1](../../../../resources/SPEC.md) — "Blockchain state management ... is out of scope. This crate validates and computes; the caller commits to state."
- [SPEC.md Section 3.1](../../../../resources/SPEC.md) — ValidationContext design, coin_records passed by caller
- [SPEC.md Section 5.1](../../../../resources/SPEC.md) — `validate_spend_bundle()` signature with all state as parameters
- [Chia L1 `mempool_manager.py:480`](https://github.com/Chia-Network/chia-blockchain/blob/main/chia/full_node/mempool_manager.py#L480) — L1 pattern: Python loads coins, Rust computes

---

## References

- [API-002](API-002.md) — No async/IO dependencies (complementary constraint at dependency level)
- [API-005](API-005.md) — ValidationError carries context instead of looking it up
- [API-008](API-008.md) — Module structure confirms no I/O modules
