# PAR-009: Condition Type Re-exports

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

---

## Summary

`dig-clvm` MUST use the `Condition<T>` type from `chia-sdk-types` rather than defining a custom condition enum. This generic type supports all CLVM condition opcodes, including the newer `SEND_MESSAGE` (opcode 66) and `RECEIVE_MESSAGE` (opcode 67) introduced in recent Chia consensus updates. By using the upstream type, `dig-clvm` automatically gains support for new opcodes as they are added to `chia-sdk-types` without requiring code changes.

The `Condition<T>` type is generic over the CLVM node representation, which allows it to work in both construction contexts (where conditions are built programmatically using the `Conditions` builder) and parsing contexts (where conditions are extracted from CLVM output using `FromClvm`). This dual-use design eliminates the need for separate condition types for different phases of the validation pipeline.

On Chia L1, conditions are represented as a Python dictionary of opcode-to-values mappings in `conditions_dict` (see `condition_tools.py`). The Rust ecosystem's `chia-sdk-types` provides a strongly-typed equivalent that encodes the same semantics with compile-time type safety. Using this type ensures that `dig-clvm` can correctly parse and construct any condition that `chia-consensus` can process, maintaining full parity with the L1 condition system.

---

## Specification

### Condition Type from chia-sdk-types

```rust
// Re-export from chia-sdk-types, not redefined:
pub use chia_sdk_types::Condition;

// The Condition type is generic over the node representation:
// Condition<NodePtr>  — for CLVM allocator-backed nodes (parsing)
// Condition<TreeNode> — for owned tree nodes (construction)
```

### Supported Condition Opcodes

The `Condition<T>` enum includes variants for all consensus-recognized opcodes:

```rust
// From chia-sdk-types (simplified):
pub enum Condition<T> {
    // Signature conditions (opcodes 48-55)
    AggSigUnsafe { public_key: G1Element, message: Bytes },         // 48
    AggSigMe { public_key: G1Element, message: Bytes },             // 49
    AggSigParent { public_key: G1Element, message: Bytes },         // 50
    AggSigPuzzle { public_key: G1Element, message: Bytes },         // 51
    AggSigAmount { public_key: G1Element, message: Bytes },         // 52
    AggSigPuzzleAmount { public_key: G1Element, message: Bytes },   // 53
    AggSigParentAmount { public_key: G1Element, message: Bytes },   // 54
    AggSigParentPuzzle { public_key: G1Element, message: Bytes },   // 55

    // Coin creation (opcode 51)
    CreateCoin { puzzle_hash: Bytes32, amount: u64, memos: Vec<Bytes> },

    // Timelock conditions
    AssertSecondsRelative { seconds: u64 },
    AssertSecondsAbsolute { seconds: u64 },
    AssertHeightRelative { height: u32 },
    AssertHeightAbsolute { height: u32 },
    AssertBeforeSecondsRelative { seconds: u64 },
    AssertBeforeSecondsAbsolute { seconds: u64 },
    AssertBeforeHeightRelative { height: u32 },
    AssertBeforeHeightAbsolute { height: u32 },

    // Coin identity assertions
    AssertMyCoinId { coin_id: Bytes32 },
    AssertMyParentId { parent_id: Bytes32 },
    AssertMyPuzzleHash { puzzle_hash: Bytes32 },
    AssertMyAmount { amount: u64 },
    AssertMyBirthSeconds { seconds: u64 },
    AssertMyBirthHeight { height: u32 },
    AssertEphemeral,

    // Inter-coin assertions
    AssertCoinAnnouncement { announcement_id: Bytes32 },
    CreateCoinAnnouncement { message: Bytes },
    AssertPuzzleAnnouncement { announcement_id: Bytes32 },
    CreatePuzzleAnnouncement { message: Bytes },

    // Message conditions (opcodes 66-67)
    SendMessage { mode: u8, message: Bytes, destination: T },       // 66
    ReceiveMessage { mode: u8, message: Bytes, source: T },         // 67

    // Fee
    ReserveFee { amount: u64 },

    // Softfork
    Softfork { cost: u64, rest: T },

    // Remark (no-op, for embedding data)
    Remark { rest: T },
}
```

### Construction Usage (Conditions Builder)

```rust
use chia_sdk_types::Conditions;

// Building conditions programmatically:
let conditions = Conditions::new()
    .create_coin(puzzle_hash, amount, vec![memo])
    .agg_sig_me(public_key, message)
    .assert_height_relative(10)
    .send_message(mode, message, destination)
    .reserve_fee(1000);
```

### Parsing Usage (FromClvm)

```rust
use chia_sdk_types::Condition;
use clvmr::{Allocator, NodePtr};

// Parsing conditions from CLVM execution output:
let allocator = Allocator::new();
// ... run CLVM program ...
let conditions: Vec<Condition<NodePtr>> = parse_conditions(&allocator, output)?;

for condition in &conditions {
    match condition {
        Condition::CreateCoin { puzzle_hash, amount, .. } => {
            // Process coin creation
        }
        Condition::SendMessage { mode, message, .. } => {
            // Process cross-coin message (opcode 66)
        }
        Condition::ReceiveMessage { mode, message, .. } => {
            // Process cross-coin message receipt (opcode 67)
        }
        _ => {}
    }
}
```

### What NOT To Do

```rust
// WRONG: Custom condition enum
pub enum DigCondition {
    CreateCoin(Bytes32, u64),
    AggSigMe(G1Element, Bytes),
    // Missing SEND_MESSAGE, RECEIVE_MESSAGE, and future opcodes!
}

// WRONG: Opcode-based dispatch without typed enum
fn process_condition(opcode: u8, args: &[u8]) { ... }

// WRONG: Partial condition support
// Any subset that omits opcodes 66/67 is insufficient
```

---

## Acceptance Criteria

- [ ] `Condition<T>` from `chia-sdk-types` is used for all condition handling, not a custom enum.
- [ ] `SEND_MESSAGE` (opcode 66) and `RECEIVE_MESSAGE` (opcode 67) are supported through the generic condition type.
- [ ] The condition type is generic over node representation, supporting both construction (`Conditions` builder) and parsing (`FromClvm`).
- [ ] No custom condition enum is defined in `dig-clvm` source code.
- [ ] The `chia-sdk-types` dependency version supports all current consensus opcodes.

---

## Implementation Notes

- **Primary file:** `src/lib.rs` or `src/types.rs` (re-export), condition processing code throughout `src/consensus/`.
- **Generic T parameter:** The `T` in `Condition<T>` is the CLVM node type. When parsing from an `Allocator`, `T = NodePtr`. When constructing, `T` may be an owned type. The validator typically works with `NodePtr`-backed conditions for efficiency.
- **Forward compatibility:** When `chia-sdk-types` adds new condition variants (e.g., for future soft forks), `dig-clvm` gains support automatically. Match statements should include a wildcard arm for unknown variants to remain forward-compatible.
- **SEND_MESSAGE/RECEIVE_MESSAGE:** These opcodes enable cross-coin communication within a block. They are validated by `chia-consensus` (VAL-009) and must be representable in the condition type. Without `chia-sdk-types::Condition`, these would need manual implementation.
- **Memos in CREATE_COIN:** The `CreateCoin` variant includes an optional `memos` field (Vec<Bytes>). Memos are not consensus-critical but are part of the condition structure.
- **Softfork condition:** The `Softfork` variant allows future consensus rule changes. Its `cost` field is charged against the CLVM cost budget. The `rest` parameter contains opaque data for the soft fork logic.

---

## Verification

### Test Plan

| Test | Type | Description | Expected Result |
|------|------|-------------|-----------------|
| Parse all opcodes | Unit test | CLVM output with every condition opcode | All parsed into correct Condition variants |
| SEND_MESSAGE parse | Unit test | CLVM output with opcode 66 | Condition::SendMessage with correct fields |
| RECEIVE_MESSAGE parse | Unit test | CLVM output with opcode 67 | Condition::ReceiveMessage with correct fields |
| Builder roundtrip | Unit test | Build conditions, serialize, parse back | Identical conditions |
| No custom enum | Code review | Search for `enum.*Condition` in dig-clvm src | Only re-exports, no custom definitions |
| Generic over T | Compile test | Use Condition<NodePtr> and Condition<TreeNode> | Both compile and work |

---

## Source Citations

- **SPEC.md Section 9.3**: "Uses chia-sdk-types::Condition<T>, not custom enum. Supports all opcodes including SEND_MESSAGE(66)/RECEIVE_MESSAGE(67)."
- **SPEC.md Section 9.3**: "Generic over node representation. Works for both construction (Conditions builder) and parsing (FromClvm)."
- **L1 reference — condition_tools.py:** Condition parsing and opcode dispatch in Python.
- **chia-sdk-types crate:** Canonical Rust condition type definitions.

---

## References

- [PAR-008](PAR-008.md) — Protocol type re-exports (same principle for Coin, CoinSpend, etc.)
- [VAL-009](../../validation/specs/VAL-009.md) — Condition validation (processes these condition types)
- [VAL-012](../../validation/specs/VAL-012.md) — BLS signature verification (processes AGG_SIG_* conditions)
- [PAR-011](PAR-011.md) — Mempool flag parity (affects which conditions are accepted)
