# BLS-003: Mempool-to-Block Cache Reuse with Same Instance

> **Authoritative requirement:** [BLS-003](../NORMATIVE.md#BLS-003)
> **Verification:** [VERIFICATION.md](../VERIFICATION.md)
> **Tracking:** [TRACKING.yaml](../TRACKING.yaml)
> **Spec reference:** [SPEC.md](../../../../resources/SPEC.md) — Section 5.1

---

## Summary

A BLS signature pairing verified during mempool validation (`validate_spend_bundle()`) must be reusable during subsequent block validation (`validate_block()`) when the same `BlsCache` instance is passed to both calls. This is the primary performance optimization enabled by the BLS cache subsystem: spend bundles admitted to the mempool have their signatures verified once, and when those same bundles are assembled into a block, the signature pairings are found in the cache and do not require re-verification.

This pattern directly mirrors Chia L1's mempool-to-block flow. On L1, the mempool manager at [`mempool_manager.py:428`](https://github.com/Chia-Network/chia-blockchain/blob/main/chia/full_node/mempool_manager.py#L428) validates incoming spend bundles and caches BLS pairings. When `create_block_generator()` at [`mempool.py:505`](https://github.com/Chia-Network/chia-blockchain/blob/main/chia/full_node/mempool.py#L505) assembles a block, the cached pairings from mempool validation are available for reuse during block-level signature verification at [`multiprocess_validation.py:62`](https://github.com/Chia-Network/chia-blockchain/blob/main/chia/consensus/multiprocess_validation.py#L62). This avoids a redundant O(n) BLS verification pass where n is the number of signature pairings in the block.

The reuse mechanism works because the `BlsCache` instance is passed by mutable reference (`&mut BlsCache`) and persists across both function calls. The cache keys are the BLS pairing tuples `(public_key, message)`, which are deterministic for a given spend. As long as the same `BlsCache` instance is used, pairings cached during `validate_spend_bundle()` will be found during `validate_block()`. This requirement depends on [BLS-001](BLS-001.md) for the `Option<&mut BlsCache>` parameter and [BLS-004](BLS-004.md) for using the upstream `chia-bls::BlsCache` type.

---

## Specification

### Reuse Flow

The expected usage pattern for a DIG validator node:

```rust
use chia_bls::BlsCache;

// Step 1: Validator maintains a long-lived cache
let mut bls_cache = BlsCache::default();

// Step 2: Mempool validation -- cache is populated
for bundle in incoming_bundles {
    let result = validate_spend_bundle(
        &bundle,
        &context,
        &config,
        Some(&mut bls_cache),  // pairings cached here
    )?;
    mempool.add(bundle, result);
}

// Step 3: Block construction
let block_result = build_block_generator(
    &mempool.top_bundles(),
    &context,
    max_block_cost,
)?;

// Step 4: Block validation -- cache hits avoid re-verification
let block_spend_result = validate_block(
    &block_result.generator,
    &block_result.block_refs,
    &context,
    &config,
    Some(&mut bls_cache),  // same instance, pairings reused
)?;
```

### Cache Key Determinism

For cache reuse to work, the BLS pairings generated during spend bundle validation must produce the same cache keys as those generated during block validation. This is guaranteed by the following invariants:

1. **Same public keys**: The `AGG_SIG_*` conditions extracted from CLVM execution contain the same public keys regardless of whether execution occurs at the spend-bundle level or block-generator level.

2. **Same messages**: The domain-separated messages (`msg + addendum + additional_data[opcode]`) are constructed from the same coin data and opcode, producing identical byte sequences (see [PAR-004](../../parity/specs/PAR-004.md)).

3. **Same signature**: The aggregated BLS signature is the same whether verified at the bundle level or the block level (assuming the block includes the same spends).

### Performance Expectation

When the cache is warm from mempool validation:

- **Cache hit**: BLS pairing lookup is O(1) hash table access.
- **Cache miss**: Full BLS12-381 pairing verification (expensive elliptic curve operation).
- **Expected ratio**: For a block composed entirely of mempool-validated bundles, the cache hit rate should approach 100%.

### Edge Cases

- **Evicted bundles**: If a spend bundle was validated but later evicted from the mempool, its cache entries may still be present. This is harmless -- stale cache entries do not affect correctness (per [BLS-005](BLS-005.md)).
- **Partial blocks**: If only some bundles in a block were mempool-validated with the cache, only those bundles benefit from cache hits. Remaining bundles are verified from scratch.
- **Cache size**: The `BlsCache` from `chia-bls` manages its own memory. The caller does not need to configure a maximum size.

---

## Acceptance Criteria

- [ ] A `BlsCache` populated by `validate_spend_bundle()` produces cache hits when the same instance is passed to `validate_block()` for the same spends
- [ ] Block validation with a warm cache completes faster than block validation with a cold cache (measurable via benchmark)
- [ ] The `SpendResult` from block validation is identical whether the cache is warm or cold
- [ ] The same `BlsCache` instance can be reused across multiple `validate_spend_bundle()` calls without errors
- [ ] Cache entries from earlier `validate_spend_bundle()` calls persist and remain valid for later `validate_block()` calls

---

## Implementation Notes

- The `BlsCache` from `chia-bls` uses a `HashMap` internally keyed by the pairing augmented message. No custom cache implementation is needed.
- The mutable borrow (`&mut BlsCache`) means only one validation call can use the cache at a time. For concurrent mempool validation, the caller must synchronize access (e.g., `Mutex<BlsCache>`).
- Cache invalidation is not needed. BLS verification is deterministic: if a pairing was valid once, it is always valid. The only reason to clear the cache is to reclaim memory.
- The `build_block_generator()` function does not take a cache parameter because it does not perform BLS verification -- it only assembles the generator program.

---

## Verification

### Test Plan

1. **Cache reuse -- warm path**:
   - Create a `BlsCache::default()`.
   - Build a valid `SpendBundle` using `Simulator`.
   - Call `validate_spend_bundle(&bundle, &ctx, &cfg, Some(&mut cache))`.
   - Assert success and verify cache is non-empty.
   - Build a block generator from the same bundle.
   - Call `validate_block(&gen, &refs, &ctx, &cfg, Some(&mut cache))`.
   - Assert success. Verify the result matches the spend-bundle-level result (same additions/removals).

2. **Cache reuse -- cold path comparison**:
   - Repeat the above test with a fresh `BlsCache::default()` for block validation (cold cache).
   - Assert the `SpendResult` is identical to the warm-cache result.

3. **Benchmark test**:
   - Build a block with 50+ spend bundles.
   - Validate all bundles with `Some(&mut cache)`.
   - Time `validate_block()` with the warm cache.
   - Time `validate_block()` with a cold `BlsCache::default()`.
   - Assert warm-cache time is measurably less than cold-cache time (at least 2x faster for blocks with many signatures).

4. **Multi-bundle accumulation**:
   - Validate 10 distinct spend bundles sequentially with the same `BlsCache`.
   - Build a block containing all 10 bundles.
   - Call `validate_block()` with the accumulated cache.
   - Assert all pairings hit the cache (no new entries added to cache during block validation).

5. **Partial cache coverage**:
   - Validate 5 out of 10 bundles with the cache.
   - Build a block containing all 10 bundles.
   - Call `validate_block()` with the partially-warm cache.
   - Assert success. Verify that 5 bundles hit cache and 5 are verified from scratch.

### Expected Test Files

- `tests/cache_tests.rs` -- BLS-003 mempool-to-block reuse tests
- `tests/block_tests.rs` -- block validation with warm/cold cache comparison

---

## Source Citations

- Chia L1 mempool validation with cache: [`mempool_manager.py:428`](https://github.com/Chia-Network/chia-blockchain/blob/main/chia/full_node/mempool_manager.py#L428)
- Chia L1 block generation: [`mempool.py:505-529`](https://github.com/Chia-Network/chia-blockchain/blob/main/chia/full_node/mempool.py#L505)
- Chia L1 block validation: [`multiprocess_validation.py:62`](https://github.com/Chia-Network/chia-blockchain/blob/main/chia/consensus/multiprocess_validation.py#L62)
- `chia-bls::BlsCache`: [`chia-bls` crate](https://crates.io/crates/chia-bls)

---

## References

- [BLS-001](BLS-001.md) -- Optional BlsCache parameter (interface requirement)
- [BLS-004](BLS-004.md) -- Uses `chia-bls::BlsCache` directly (type requirement)
- [BLS-005](BLS-005.md) -- Cache does not affect correctness (safety invariant)
- [PAR-004](../../parity/specs/PAR-004.md) -- BLS domain separation (deterministic message construction)
