# PAR-007: Per-Spend Cost Limit of 11 Billion

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

---

## Summary

The per-spend cost limit in `dig-clvm` must be `11,000,000,000` (11 billion), matching Chia L1's `MAX_BLOCK_COST_CLVM` defined at [`default_constants.py:68`](https://github.com/Chia-Network/chia-blockchain/blob/main/chia/consensus/default_constants.py#L68). This value represents the maximum total CLVM cost (execution cost plus condition costs per [PAR-006](PAR-006.md)) that a single spend bundle can consume. Any spend bundle whose total cost exceeds this limit must be rejected with a cost-exceeded error.

On Chia L1, `MAX_BLOCK_COST_CLVM = 11,000,000,000` serves as both the per-spend limit and the per-block limit. On DIG L2, the per-spend limit is the same (11B), but the per-block limit is configurable via `ValidationConfig` and may differ. This is the only permitted cost divergence from L1: the per-block cost limit for DIG L2 can be set higher (e.g., 50x the per-spend limit) to allow more transactions per block, while keeping the per-spend limit identical to prevent individual spends from being too expensive.

This limit is enforced by passing `max_cost = 11_000_000_000` to the `chia-consensus` functions that execute CLVM programs. The `run_spendbundle()` function checks cost during execution and returns an error if the limit is exceeded mid-execution (without running the program to completion). The `run_puzzle()` convenience function from `chia-sdk-types` also uses this limit by default. This value must not be hardcoded in multiple places; it should come from `ConsensusConstants` or `ValidationConfig`.

---

## Specification

### Cost Limit Value

```rust
/// Maximum CLVM cost per spend bundle, matching L1's MAX_BLOCK_COST_CLVM.
const MAX_COST_PER_SPEND: u64 = 11_000_000_000;

// This value comes from ConsensusConstants:
// constants.max_block_cost_clvm == 11_000_000_000
```

### Enforcement Points

1. **Spend bundle validation**:
   ```rust
   pub fn validate_spend_bundle(
       bundle: &SpendBundle,
       context: &ValidationContext,
       config: &ValidationConfig,
       bls_cache: Option<&mut BlsCache>,
   ) -> Result<SpendResult, ValidationError> {
       let max_cost = config.max_cost_per_spend();  // == 11_000_000_000
       let conditions = run_spendbundle(
           &mut allocator, bundle, max_cost, height, constants, flags
       )?;
       // run_spendbundle returns Err if cost > max_cost
       // ...
   }
   ```

2. **Puzzle execution** (via `chia-sdk-types`):
   ```rust
   use chia_sdk_types::run_puzzle;
   // run_puzzle internally uses 11_000_000_000 as the cost limit:
   // run_program(allocator, &ChiaDialect::new(0), puzzle, solution, 11_000_000_000)
   ```

### Per-Block Cost (configurable divergence)

The per-block cost limit is separate and configurable:

```rust
pub struct ValidationConfig {
    /// Per-spend cost limit (must be 11_000_000_000 for L1 parity)
    pub max_cost_per_spend: u64,
    /// Per-block cost limit (L2-configurable, e.g., 550_000_000_000 = 50x per-spend)
    pub max_cost_per_block: u64,
    // ...
}

impl ValidationConfig {
    pub fn default() -> Self {
        Self {
            max_cost_per_spend: 11_000_000_000,
            max_cost_per_block: 550_000_000_000,  // L2 default: 50x per-spend
            // ...
        }
    }
}
```

### Error Behavior

When cost exceeds the limit:

```rust
// run_spendbundle returns Err(ValidationErr) which dig-clvm wraps:
Err(ValidationError::CostExceeded {
    cost: actual_cost,
    limit: 11_000_000_000,
})
```

The error must be returned as soon as the limit is exceeded during execution, not after the program finishes. This prevents malicious programs from consuming unbounded resources.

---

## Acceptance Criteria

- [ ] `validate_spend_bundle()` passes `11_000_000_000` as the cost limit to `chia-consensus`
- [ ] A spend bundle costing exactly `11_000_000_000` is accepted
- [ ] A spend bundle costing `11_000_000_001` is rejected with a cost-exceeded error
- [ ] The per-block cost limit is configurable via `ValidationConfig` (separate from per-spend)
- [ ] `run_puzzle()` (re-exported) uses `11_000_000_000` as its internal cost limit

---

## Implementation Notes

- The value `11_000_000_000` fits in a `u64` (max ~18.4 * 10^18). The `clvmr::Cost` type is `u64`.
- The cost limit is checked incrementally during CLVM execution. The `clvmr` runtime tracks cost after each operator and aborts if the limit is exceeded.
- For block validation, the per-block cost limit applies to the aggregate cost of all spends in the block. Individual spends within the block are still limited by the per-spend limit.
- The `build_block_generator()` function uses `max_cost` (the per-block limit) to determine how many bundles fit in a block.
- `ConsensusConstants.max_block_cost_clvm` in `chia-consensus` is where this value is defined upstream. DIG's `NetworkConstants` should set this to `11_000_000_000`.

---

## Verification

### Test Plan

1. **Exact limit -- pass**:
   - Construct a spend whose total cost is exactly `11_000_000_000`.
   - Validate via `validate_spend_bundle()`.
   - Assert `Ok(SpendResult { .. })`.

2. **Over limit -- fail**:
   - Construct a spend whose total cost is `11_000_000_001` or higher.
   - Validate via `validate_spend_bundle()`.
   - Assert `Err(ValidationError::CostExceeded { .. })`.

3. **Under limit -- pass**:
   - Construct a typical spend (cost ~10M).
   - Validate. Assert `Ok`.

4. **Default config value**:
   ```rust
   let config = ValidationConfig::default();
   assert_eq!(config.max_cost_per_spend, 11_000_000_000);
   ```

5. **Per-block vs per-spend separation**:
   - Set `max_cost_per_block = 22_000_000_000` (2x per-spend).
   - Build a block with 2 bundles, each costing ~10B.
   - Assert block validation succeeds (total ~20B < 22B limit).
   - Build a block with 3 bundles, each costing ~10B.
   - Assert block validation fails (total ~30B > 22B limit).

6. **run_puzzle limit**:
   - Call `run_puzzle()` with a program that costs more than 11B.
   - Assert an error is returned (cost limit exceeded).

### Expected Test Files

- `tests/cost_tests.rs` -- PAR-007 cost limit enforcement tests

---

## Source Citations

- Chia L1 `MAX_BLOCK_COST_CLVM`: [`default_constants.py:68`](https://github.com/Chia-Network/chia-blockchain/blob/main/chia/consensus/default_constants.py#L68)
- `run_puzzle()` cost limit: [SPEC.md Section 2.7](../../../../resources/SPEC.md) -- "11B cost limit (mirrors L1's MAX_BLOCK_COST_CLVM)"
- dig-clvm L2 cost constants: [SPEC.md Section 3.1](../../../../resources/SPEC.md)

---

## References

- [PAR-006](PAR-006.md) -- Per-condition costs (contribute to total cost that is limited here)
- [PAR-001](PAR-001.md) -- CLVM execution (execution cost is the base cost)
- [PAR-010](PAR-010.md) -- Block generators (per-block cost limit applies during block validation)
