# BLK-001: `build_block_generator` Entry Point

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

---

## Summary

BLK-001 defines the public entry point for block construction in dig-clvm. The function `build_block_generator()` accepts a slice of `SpendBundle` values, a `ValidationContext` carrying L2 chain state, and a `max_cost: Cost` budget, and returns `Result<BlockGeneratorResult, ValidationError>`. This is the Path B counterpart to Path A's `validate_spend_bundle()`, assembling multiple mempool-validated bundles into a single compressed block-level CLVM program.

The function mirrors Chia L1's `create_block_generator()` at [`mempool.py:505`](https://github.com/Chia-Network/chia-blockchain/blob/main/chia/full_node/mempool.py#L505), which is called by the full node when building a new block from the mempool. On L1, this function iterates pending transactions, computes their cost, and assembles them into a block generator program. dig-clvm provides the same behavior as a Rust function that DIG validators invoke to produce blocks for their L2 chain.

The `ValidationContext` parameter carries the height, timestamp, genesis challenge, and coin records needed to validate each bundle as it is added. The `max_cost` parameter is the total CLVM cost budget for the block (typically `L2_MAX_COST_PER_BLOCK = 550_000_000_000`). The function must return a well-formed `BlockGeneratorResult` on success, or a `ValidationError` if no bundles could be included or if an internal error occurs.

---

## Specification

### Function Signature

```rust
pub fn build_block_generator(
    bundles: &[SpendBundle],
    context: &ValidationContext,
    max_cost: Cost,
) -> Result<BlockGeneratorResult, ValidationError>;
```

### Parameters

| Parameter | Type | Description |
|-----------|------|-------------|
| `bundles` | `&[SpendBundle]` | Ordered slice of spend bundles from the mempool. The caller pre-sorts by fee/cost ratio (highest first) to maximize fee revenue. |
| `context` | `&ValidationContext` | L2 chain state: height, timestamp, genesis challenge, coin records for all coins referenced by the bundles. |
| `max_cost` | `Cost` (`u64`) | Maximum total CLVM cost allowed for the block. Bundles whose cost would push the total past this limit are skipped. |

### Return Value

On success, returns `Ok(BlockGeneratorResult)` containing the compressed block generator, aggregated signature, additions, removals, total cost, and count of included bundles (see [BLK-004](BLK-004.md)).

On failure, returns `Err(ValidationError)` with an appropriate error variant. Failures may occur if CLVM execution fails for all bundles, if `solution_generator_backrefs()` fails, or if internal allocation errors occur.

### Behavioral Contract

1. The function MUST accept any non-empty slice of `SpendBundle` values.
2. The function MUST accept an empty slice and return an appropriate result or error (implementation-defined whether an empty block is valid).
3. The function MUST use the provided `ValidationContext` for all validation decisions (height, timestamp, coin existence).
4. The function MUST respect the `max_cost` budget as specified in [BLK-002](BLK-002.md).
5. The function MUST NOT perform any I/O, database lookups, or network calls.

### L1 Correspondence

| dig-clvm | Chia L1 | Source |
|----------|---------|--------|
| `build_block_generator()` | `create_block_generator()` | [`mempool.py:505`](https://github.com/Chia-Network/chia-blockchain/blob/main/chia/full_node/mempool.py#L505) |
| `bundles` parameter | `MempoolItem` list | Sorted by fee-per-cost in `create_block_generator()` |
| `max_cost` parameter | `MAX_BLOCK_COST_CLVM` | [`default_constants.py:68`](https://github.com/Chia-Network/chia-blockchain/blob/main/chia/consensus/default_constants.py#L68) |

---

## Acceptance Criteria

- [ ] `build_block_generator` compiles with the exact signature `(&[SpendBundle], &ValidationContext, Cost) -> Result<BlockGeneratorResult, ValidationError>`
- [ ] Calling with a single valid bundle returns `Ok(BlockGeneratorResult)` with `bundles_included == 1`
- [ ] Calling with multiple valid bundles returns `Ok(BlockGeneratorResult)` with `bundles_included >= 1`
- [ ] The returned `BlockGeneratorResult` contains all required fields (generator, block_refs, aggregated_signature, additions, removals, cost, bundles_included)
- [ ] The function does not panic on empty input or bundles exceeding `max_cost`
- [ ] The function does not perform any I/O or storage lookups

---

## Implementation Notes

- The function is the primary block construction API for DIG validators. It should be called after the mempool has been sorted by fee/cost ratio.
- The caller is responsible for providing a `ValidationContext` with all coin records that the bundles reference. Missing coin records will cause per-bundle validation failures, and those bundles will be skipped (not a fatal error for the block).
- The `max_cost` parameter corresponds to `L2_MAX_COST_PER_BLOCK` from `dig-constants`, which is `550_000_000_000` (50x L1's per-spend limit of `11_000_000_000`).
- Internally, this function iterates bundles per [BLK-002](BLK-002.md), uses `solution_generator_backrefs()` per [BLK-003](BLK-003.md), and produces the result structure per [BLK-004](BLK-004.md).

---

## Verification

### Test Plan

| Test Case | Input | Expected Outcome |
|-----------|-------|------------------|
| Single valid bundle | One `SpendBundle` with cost < `max_cost` | `Ok(BlockGeneratorResult)` with `bundles_included == 1` |
| Multiple valid bundles | Three bundles all fitting within `max_cost` | `Ok(BlockGeneratorResult)` with `bundles_included == 3` |
| Empty bundle slice | `&[]` | Returns `Ok` with `bundles_included == 0` or `Err` (implementation-defined) |
| Type signature check | Compile-time | Function signature matches the spec exactly |
| No side effects | Call with valid input, inspect for I/O | No file, network, or database operations |

### Verification Method

- **Unit test**: Call `build_block_generator` with valid arguments, assert return type is `Result<BlockGeneratorResult, ValidationError>` and all fields are populated.
- **Compile-time check**: The function signature is enforced by the Rust type system. If the signature changes, dependent code will fail to compile.

---

## Source Citations

- Chia L1 `create_block_generator()`: [`mempool.py:505`](https://github.com/Chia-Network/chia-blockchain/blob/main/chia/full_node/mempool.py#L505)
- L1 block cost constant: [`default_constants.py:68`](https://github.com/Chia-Network/chia-blockchain/blob/main/chia/consensus/default_constants.py#L68)
- `NewBlockGenerator` (L1 output type): [`generator_types.py:28`](https://github.com/Chia-Network/chia-blockchain/blob/main/chia/types/generator_types.py#L28)

---

## References

- [BLK-002](BLK-002.md) — Cost-aware bundle iteration
- [BLK-003](BLK-003.md) — Uses `solution_generator_backrefs`
- [BLK-004](BLK-004.md) — `BlockGeneratorResult` structure
- [BLK-005](BLK-005.md) — Aggregated signature
- [SPEC.md Section 5](../../../../resources/SPEC.md) — Public API surface
- [SPEC.md Section 6](../../../../resources/SPEC.md) — Validation flow (Path B)
