# TYP-003: Per-CF Configuration

| Link | Path |
|------|------|
| **Normative** | [NORMATIVE.md](../NORMATIVE.md) |
| **Verification** | [VERIFICATION.md](../VERIFICATION.md) |
| **Tracking** | [TRACKING.yaml](../TRACKING.yaml) |
| **Spec** | [SPEC.md](../../../../resources/SPEC.md) Section 2.4 |

---

## Summary

Each RocksDB column family MUST be configured with specific compaction, bloom filter, compression, and BlobDB settings optimized for its access pattern.

---

## Specification

### CF_BLOCKS Configuration

```rust
fn blocks_cf_options(config: &BlockStoreConfig) -> Options {
    let mut opts = Options::default();
    // Universal compaction: better for write-heavy, large-value workloads
    opts.set_compaction_style(DBCompactionStyle::Universal);

    // BlobDB: offload large block values to blob files
    if config.enable_blob_db {
        opts.set_enable_blob_files(true);
        opts.set_min_blob_size(512); // Values >= 512 bytes go to blob storage
        opts.set_blob_compression_type(DBCompressionType::Zstd);
    }

    // No bloom filter: blocks are always looked up by exact hash key
    // (bloom filters help with non-existent key checks, not exact lookups)

    opts
}
```

**Rationale:** Blocks are large (typically 1-100 KB), write-heavy, and always accessed by exact hash. Universal compaction reduces write amplification. BlobDB separates large values from the LSM tree for better compaction performance.

### CF_HEADERS Configuration

```rust
fn headers_cf_options() -> Options {
    let mut opts = Options::default();
    // Level compaction: good for read-heavy, smaller-value workloads
    opts.set_compaction_style(DBCompactionStyle::Level);

    // Bloom filter: speeds up point lookups and non-existent key checks
    opts.set_bloom_filter(DEFAULT_BLOOM_BITS_PER_KEY as f64, false);

    // No compression: headers are small, compression overhead not worth it
    opts.set_compression_type(DBCompressionType::None);

    opts
}
```

**Rationale:** Headers are small (~200 bytes), read frequently, and benefit from bloom filters for fast existence checks during chain traversal.

### CF_ATTESTED Configuration

```rust
fn attested_cf_options() -> Options {
    let mut opts = Options::default();
    opts.set_compaction_style(DBCompactionStyle::Level);
    opts.set_bloom_filter(DEFAULT_BLOOM_BITS_PER_KEY as f64, false);
    opts
}
```

**Rationale:** Attested blocks have a similar access pattern to headers. Bloom filters help with attestation existence checks.

### CF_CANONICAL Configuration

```rust
fn canonical_cf_options() -> Options {
    let mut opts = Options::default();
    opts.set_compaction_style(DBCompactionStyle::Level);
    // No bloom filter: sequential height lookups, not random existence checks
    // No compression: values are exactly 32 bytes (hash), not compressible
    opts.set_compression_type(DBCompressionType::None);
    opts
}
```

**Rationale:** The canonical index maps height (8 bytes) to hash (32 bytes). Fixed-size values do not benefit from compression. Sequential access by height does not benefit from bloom filters.

### CF_CHECKPOINTS Configuration

```rust
fn checkpoints_cf_options() -> Options {
    let mut opts = Options::default();
    opts.set_compaction_style(DBCompactionStyle::Level);
    // Large target file size: checkpoints are infrequent, minimize compaction
    opts.set_target_file_size_base(256 * 1024 * 1024); // 256 MB
    opts
}
```

**Rationale:** Checkpoints are written once per epoch and rarely updated. Large target file sizes reduce unnecessary compaction.

### CF_METADATA Configuration

```rust
fn metadata_cf_options() -> Options {
    let mut opts = Options::default();
    opts.set_compaction_style(DBCompactionStyle::Level);
    // Default settings: metadata is tiny and rarely accessed
    opts
}
```

**Rationale:** Metadata has very few keys (tip, genesis hash, etc.) and minimal I/O. Default settings are sufficient.

---

## Acceptance Criteria

- [x] CF_BLOCKS uses Universal compaction
- [x] CF_BLOCKS has BlobDB enabled with min_blob_size = 512 (when config.enable_blob_db)
- [x] CF_BLOCKS does not set a bloom filter
- [x] CF_HEADERS uses Level compaction
- [x] CF_HEADERS has a bloom filter with 10 bits per key
- [x] CF_HEADERS has compression disabled
- [x] CF_ATTESTED uses Level compaction
- [x] CF_ATTESTED has a bloom filter with 10 bits per key
- [x] CF_CANONICAL uses Level compaction
- [x] CF_CANONICAL has no bloom filter
- [x] CF_CANONICAL has compression disabled
- [x] CF_CHECKPOINTS uses Level compaction
- [x] CF_CHECKPOINTS has a large target file size
- [x] CF_METADATA uses Level compaction

---

## Implementation Notes

- Column family options are built in `src/cf_options.rs` (`column_family_descriptors`) and used by `BlockStore::open()` / `open_readonly()`.
- The `rocksdb` crate's `Options` type is used for per-CF configuration.
- BlobDB support requires the `rocksdb` crate to be compiled with BlobDB feature support.
- Bloom filter settings use `set_bloom_filter(bits_per_key, block_based)` where `block_based = false` for full filters.

---

## Test Plan

| Test Name | Type | Description |
|-----------|------|-------------|
| `test_blocks_cf_universal_compaction` | integration | Open store, verify CF_BLOCKS uses Universal compaction via RocksDB options inspection |
| `test_blocks_cf_blobdb_enabled` | integration | Open store with enable_blob_db=true, verify BlobDB is active for CF_BLOCKS |
| `test_headers_cf_level_compaction` | integration | Open store, verify CF_HEADERS uses Level compaction |
| `test_headers_cf_has_bloom_filter` | integration | Open store, verify CF_HEADERS bloom filter is configured |
| `test_headers_cf_no_compression` | integration | Open store, verify CF_HEADERS has no compression |
| `test_canonical_cf_no_bloom` | integration | Open store, verify CF_CANONICAL has no bloom filter |
| `test_canonical_cf_no_compression` | integration | Open store, verify CF_CANONICAL compression is disabled |
| `test_checkpoints_cf_large_target` | integration | Open store, verify CF_CHECKPOINTS has a large target file size |
| `test_metadata_cf_level_compaction` | integration | Open store, verify CF_METADATA uses Level compaction |

---

## Expected Test Files

- `tests/typ_003_tests.rs`
