# BLK-003: Uses `solution_generator_backrefs` for Generator Construction

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

---

## Summary

BLK-003 requires that the block generator program produced by `build_block_generator()` MUST be constructed using `solution_generator_backrefs()` from the `chia-consensus` crate. This function compresses the block-level CLVM program by using CLVM back-references to deduplicate repeated puzzle bytecodes, producing a smaller and more efficient generator. dig-clvm MUST NOT hand-roll its own generator construction logic.

This mirrors Chia L1's approach at [`mempool.py:529`](https://github.com/Chia-Network/chia-blockchain/blob/main/chia/full_node/mempool.py#L529), where `create_block_generator()` calls `solution_generator_backrefs()` to assemble the block program. The companion function `simple_solution_generator_backrefs()` at [`bundle_tools.py:15`](https://github.com/Chia-Network/chia-blockchain/blob/main/chia/full_node/bundle_tools.py#L15) provides the same functionality for simpler cases. On L1, this deduplication is critical because many transactions in a block use the same standard puzzle (e.g., the standard transaction puzzle), and back-references avoid repeating the full puzzle bytecode for each spend.

By delegating to `chia-consensus` for generator construction, dig-clvm achieves parity with L1 by construction. The compressed generator can be decompressed and executed by `run_block_generator2()` (see [BLK-007](BLK-007.md)), maintaining the round-trip property required by [BLK-009](BLK-009.md). Any hand-rolled generator construction would risk subtle incompatibilities with the decompression logic in `chia-consensus`.

---

## Specification

### Required Function Call

```rust
// Inside build_block_generator(), after collecting spends from included bundles:
let generator = solution_generator_backrefs(spends)?;
```

Where `spends` is the list of `(coin, puzzle_reveal, solution)` tuples from all included bundles, in order.

### Back-Reference Deduplication

CLVM back-references work by replacing repeated subtrees with references to their first occurrence. When multiple spends share the same puzzle (e.g., the standard transaction puzzle `p2_delegated_puzzle_or_hidden_puzzle`), the puzzle bytecode appears once and subsequent spends reference it:

```
# Without back-references (naive):
(spend1_puzzle spend1_solution)
(spend2_puzzle spend2_solution)  # spend2_puzzle == spend1_puzzle (duplicated)
(spend3_puzzle spend3_solution)  # spend3_puzzle == spend1_puzzle (duplicated)

# With back-references (compressed):
(spend1_puzzle spend1_solution)
(BACKREF_TO_spend1_puzzle spend2_solution)  # ~32 bytes instead of ~500+
(BACKREF_TO_spend1_puzzle spend3_solution)  # ~32 bytes instead of ~500+
```

### Behavioral Rules

1. **Delegation required**: The block generator MUST be produced by calling `solution_generator_backrefs()` from `chia-consensus`. No hand-rolled CLVM serialization or generator construction is permitted.

2. **Input ordering**: The spends passed to `solution_generator_backrefs()` MUST preserve the order of bundles as specified by [BLK-002](BLK-002.md). Within each bundle, spends MUST preserve the order from the `SpendBundle`'s `coin_spends` field.

3. **Deduplication**: The resulting generator MUST use back-references for repeated puzzle bytecodes. This is an inherent property of `solution_generator_backrefs()`, not something dig-clvm needs to implement separately.

4. **Output type**: The output of `solution_generator_backrefs()` is a `BlockGenerator` (re-exported from `chia_consensus::run_block_generator::BlockGenerator`), which is stored in `BlockGeneratorResult.generator`.

### L1 Correspondence

| dig-clvm | Chia L1 | Source |
|----------|---------|--------|
| `solution_generator_backrefs()` | `solution_generator_backrefs()` | [`mempool.py:529`](https://github.com/Chia-Network/chia-blockchain/blob/main/chia/full_node/mempool.py#L529) |
| Same function | `simple_solution_generator_backrefs()` | [`bundle_tools.py:15`](https://github.com/Chia-Network/chia-blockchain/blob/main/chia/full_node/bundle_tools.py#L15) |
| `BlockGenerator` type | `BlockGenerator` | [`generator_types.py:15`](https://github.com/Chia-Network/chia-blockchain/blob/main/chia/types/generator_types.py#L15) |

---

## Acceptance Criteria

- [ ] `build_block_generator()` calls `solution_generator_backrefs()` (verified by code review / grep)
- [ ] No hand-rolled CLVM generator serialization exists in dig-clvm
- [ ] The resulting generator is of type `BlockGenerator` from `chia-consensus`
- [ ] Bundles sharing the same puzzle produce a smaller generator than naive serialization (back-references active)
- [ ] The generator produced by `solution_generator_backrefs()` can be successfully executed by `run_block_generator2()` (round-trip)

---

## Implementation Notes

- The `solution_generator_backrefs()` function is provided by the `chia-consensus` crate. It takes a list of spend tuples and produces a compressed CLVM program.
- The `BlockGenerator` type is re-exported from `chia_consensus::run_block_generator::BlockGenerator` as noted in [SPEC.md Section 5](../../../../resources/SPEC.md).
- Back-reference deduplication is especially effective for blocks containing many standard transactions, where the puzzle is identical across spends. A block with 100 standard transactions might see 50-70% size reduction compared to naive serialization.
- The `block_refs` field in `BlockGeneratorResult` (see [BLK-004](BLK-004.md)) enables cross-block back-references, where a spend can reference a puzzle from a previous block's generator. For DIG's initial implementation, this may be empty if cross-block references are not used.

---

## Verification

### Test Plan

| Test Case | Input | Expected Outcome |
|-----------|-------|------------------|
| Code review | Source of `build_block_generator()` | Contains call to `solution_generator_backrefs()` |
| No hand-rolled generator | Full codebase grep | No manual CLVM serialization for generator construction |
| Deduplication effective | Two bundles with identical puzzles | `generator` byte size < 2x single-bundle generator size |
| Round-trip execution | Build generator, then execute with `run_block_generator2()` | Execution succeeds, produces valid `SpendBundleConditions` |
| Generator type check | Build generator | `result.generator` is `BlockGenerator` type |

### Verification Method

- **Code review**: Grep the `build_block_generator()` implementation for `solution_generator_backrefs`. Verify no alternative generator construction exists.
- **Size comparison test**: Build a generator from two bundles sharing the standard puzzle. Compare the generator byte size to the sum of individual bundle generator sizes. The shared-puzzle generator MUST be smaller.
- **Integration test**: Build a generator and pass it to `run_block_generator2()`. Verify execution succeeds and the output conditions match the input bundles.

---

## Source Citations

- Chia L1 `solution_generator_backrefs()` call: [`mempool.py:529`](https://github.com/Chia-Network/chia-blockchain/blob/main/chia/full_node/mempool.py#L529)
- `simple_solution_generator_backrefs()`: [`bundle_tools.py:15`](https://github.com/Chia-Network/chia-blockchain/blob/main/chia/full_node/bundle_tools.py#L15)
- `BlockGenerator` type definition: [`generator_types.py:15`](https://github.com/Chia-Network/chia-blockchain/blob/main/chia/types/generator_types.py#L15)

---

## References

- [BLK-001](BLK-001.md) — `build_block_generator` entry point
- [BLK-002](BLK-002.md) — Cost-aware bundle iteration (provides the ordered spends)
- [BLK-004](BLK-004.md) — `BlockGeneratorResult` structure (stores the generator)
- [BLK-007](BLK-007.md) — `run_block_generator2` executes the generator produced here
- [BLK-009](BLK-009.md) — Round-trip consistency (build then validate)
- [SPEC.md Section 6](../../../../resources/SPEC.md) — Path B flow diagram
