# PAR-006: Per-Condition Costs Match Chia L1

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

---

## Summary

Per-condition costs in `dig-clvm` must match Chia L1 exactly: `AGG_SIG_COST = 1,200,000` (defined at [`condition_costs.py:8`](https://github.com/Chia-Network/chia-blockchain/blob/main/chia/consensus/condition_costs.py#L8)), `CREATE_COIN_COST = 1,800,000` (at [`:9`](https://github.com/Chia-Network/chia-blockchain/blob/main/chia/consensus/condition_costs.py#L9)), and `GENERIC_CONDITION_COST = 500` (at [`:13`](https://github.com/Chia-Network/chia-blockchain/blob/main/chia/consensus/condition_costs.py#L13)). These costs are added to the CLVM execution cost for each condition emitted by a spend, determining the total cost of a spend bundle. Incorrect costs would cause valid bundles to be rejected (if costs are too high) or invalid bundles to be accepted (if costs are too low), breaking consensus.

This requirement is satisfied by using `chia-consensus` directly for condition processing (per [PAR-002](PAR-002.md)). The `chia-consensus` crate applies these exact cost constants during `run_spendbundle()` as conditions are extracted. The `dig-clvm` crate must not define its own condition cost constants or override the costs applied by `chia-consensus`. Any custom cost calculation would create a divergence from L1 cost accounting.

The cost model serves two purposes: it limits the computational resources consumed by a single spend (preventing denial-of-service attacks) and it provides a fair fee market (higher-cost operations require higher fees). The `AGG_SIG_COST` is high because BLS pairing verification is computationally expensive. The `CREATE_COIN_COST` is even higher because coin creation affects the UTXO set size. The `GENERIC_CONDITION_COST` is low because most conditions (timelocks, announcements) are cheap to verify. These values are consensus-critical and immutable for a given Chia version.

---

## Specification

### Cost Constants

| Constant | Value | Applied To | L1 Reference |
|----------|-------|------------|-------------|
| `AGG_SIG_COST` | `1,200,000` | Each `AGG_SIG_*` condition (all 8 variants) | [`condition_costs.py:8`](https://github.com/Chia-Network/chia-blockchain/blob/main/chia/consensus/condition_costs.py#L8) |
| `CREATE_COIN_COST` | `1,800,000` | Each `CREATE_COIN` condition | [`condition_costs.py:9`](https://github.com/Chia-Network/chia-blockchain/blob/main/chia/consensus/condition_costs.py#L9) |
| `GENERIC_CONDITION_COST` | `500` | Each condition not in the above categories | [`condition_costs.py:13`](https://github.com/Chia-Network/chia-blockchain/blob/main/chia/consensus/condition_costs.py#L13) |

### Total Cost Computation

The total cost of a spend is:

```
total_cost = clvm_execution_cost
           + (num_agg_sig_conditions * AGG_SIG_COST)
           + (num_create_coin_conditions * CREATE_COIN_COST)
           + (num_other_conditions * GENERIC_CONDITION_COST)
```

This is computed by `chia-consensus` during `run_spendbundle()` and returned in `SpendBundleConditions.cost`.

### Example

A spend that:
- Costs 5,000,000 in CLVM execution
- Emits 2 `AGG_SIG_ME` conditions
- Emits 1 `CREATE_COIN` condition
- Emits 3 `ASSERT_*` conditions

Total cost:
```
5,000,000 + (2 * 1,200,000) + (1 * 1,800,000) + (3 * 500)
= 5,000,000 + 2,400,000 + 1,800,000 + 1,500
= 9,201,500
```

### Integration

```rust
use chia_consensus::spendbundle_conditions::run_spendbundle;

let conditions = run_spendbundle(
    &mut allocator, bundle, max_cost, height, constants, flags
)?;

// conditions.cost includes all condition costs, computed by chia-consensus
// using the exact constants from condition_costs.py
let total_cost: u64 = conditions.cost;
```

### Prohibited Patterns

```rust
// PROHIBITED: Custom cost constants
const AGG_SIG_COST: u64 = 1_200_000;  // Don't define locally
const CREATE_COIN_COST: u64 = 1_800_000;

// PROHIBITED: Custom cost calculation
fn compute_condition_cost(conditions: &[Condition]) -> u64 {
    conditions.iter().map(|c| match c {
        Condition::AggSigMe(..) => 1_200_000,
        Condition::CreateCoin(..) => 1_800_000,
        _ => 500,
    }).sum()
}

// PROHIBITED: Overriding chia-consensus costs
let adjusted_cost = conditions.cost + custom_adjustment;
```

---

## Acceptance Criteria

- [ ] A spend with one `AGG_SIG_ME` adds exactly 1,200,000 to the total cost (verified by inspecting `SpendBundleConditions.cost`)
- [ ] A spend with one `CREATE_COIN` adds exactly 1,800,000 to the total cost
- [ ] A spend with one `ASSERT_HEIGHT_ABSOLUTE` adds exactly 500 to the total cost
- [ ] No custom cost constants are defined in `dig-clvm` (`grep -r "AGG_SIG_COST\|CREATE_COIN_COST\|GENERIC_CONDITION_COST" src/` returns zero definition matches)
- [ ] Total cost matches the formula: `clvm_cost + sum(condition_costs)`

---

## Implementation Notes

- The cost constants are embedded in the `chia-consensus` Rust crate and are not configurable at runtime. This is by design: cost constants are part of consensus and cannot change without a hard fork.
- The `max_cost` parameter to `run_spendbundle()` is the cost limit (see [PAR-007](PAR-007.md)). If `total_cost > max_cost`, the function returns an error.
- The `GENERIC_CONDITION_COST` applies to conditions like `ASSERT_HEIGHT_ABSOLUTE`, `ASSERT_MY_COIN_ID`, `CREATE_COIN_ANNOUNCEMENT`, `RESERVE_FEE`, etc. -- everything that is not an `AGG_SIG_*` or `CREATE_COIN`.
- `REMARK(1)` also incurs `GENERIC_CONDITION_COST`.

---

## Verification

### Test Plan

1. **AGG_SIG_COST verification**:
   - Build a minimal spend that emits exactly 1 `AGG_SIG_ME(pk, msg)`.
   - Record the CLVM execution cost (known from the puzzle).
   - Validate via `dig-clvm` and inspect `SpendBundleConditions.cost`.
   - Assert `total_cost == clvm_cost + 1_200_000`.

2. **CREATE_COIN_COST verification**:
   - Build a minimal spend that emits exactly 1 `CREATE_COIN(puzzle_hash, amount)`.
   - Validate and assert `total_cost == clvm_cost + 1_800_000`.

3. **GENERIC_CONDITION_COST verification**:
   - Build a spend that emits exactly 1 `ASSERT_HEIGHT_ABSOLUTE(0)`.
   - Validate and assert `total_cost == clvm_cost + 500`.

4. **Combined cost verification**:
   - Build a spend with 2 `AGG_SIG_ME`, 1 `CREATE_COIN`, 3 `ASSERT_*` conditions.
   - Validate and assert:
     ```
     total_cost == clvm_cost + (2 * 1_200_000) + (1 * 1_800_000) + (3 * 500)
     ```

5. **Cost limit enforcement**:
   - Set `max_cost` to a value slightly below the expected total cost.
   - Validate and assert an error is returned (cost exceeded).
   - Set `max_cost` to a value slightly above the expected total cost.
   - Validate and assert success.

6. **Code review -- no custom constants**:
   - Run `grep -rn "1_200_000\|1200000\|1_800_000\|1800000" src/`.
   - Verify no matches define these as custom constants. (Matches in comments or documentation are acceptable.)

### Expected Test Files

- `tests/cost_tests.rs` -- PAR-006 per-condition cost verification

---

## Source Citations

- Chia L1 condition costs: [`condition_costs.py:8-13`](https://github.com/Chia-Network/chia-blockchain/blob/main/chia/consensus/condition_costs.py#L8)
- `chia-consensus` cost computation: [SPEC.md Section 2.5](../../../../resources/SPEC.md)
- dig-clvm cost model: [SPEC.md Section 7](../../../../resources/SPEC.md)

---

## References

- [PAR-001](PAR-001.md) -- CLVM execution (produces the base execution cost)
- [PAR-002](PAR-002.md) -- Condition parsing (conditions are what costs are applied to)
- [PAR-007](PAR-007.md) -- Per-spend cost limit (the threshold that total cost is compared against)
