# PAR-011: Mempool Flag Parity

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

---

## Summary

`dig-clvm` must support the same validation flag semantics as Chia L1's mempool and block validation paths. Two primary flags control validation behavior: `MEMPOOL_MODE` enables stricter CLVM execution via the `MempoolVisitor` (rejecting unknown opcodes and enforcing tighter cost rules), and `DONT_VALIDATE_SIGNATURE` skips BLS signature verification. These flags are combinable via bitwise OR, allowing four distinct validation configurations that match the L1 usage patterns.

On Chia L1, `MEMPOOL_MODE` is set in [`mempool.py:13`](https://github.com/Chia-Network/chia-blockchain/blob/main/chia/full_node/mempool.py#L13) when validating transactions for mempool admission, and `DONT_VALIDATE_SIGNATURE` is set in [`mempool.py:14`](https://github.com/Chia-Network/chia-blockchain/blob/main/chia/full_node/mempool.py#L14) for pre-validation passes where signature checking is deferred. Block validation typically uses neither flag (flags = 0), applying the most permissive consensus rules. The flags are passed as a `u32` bitfield to `chia-consensus` functions, which dispatch to the appropriate visitor and signature handling logic.

`dig-clvm` exposes these flags through the `ValidationConfig.flags` field and forwards them unchanged to `chia-consensus`. The flag values, semantics, and combination rules must exactly match L1 to ensure that mempool admission decisions and block validation results are identical across implementations. Any divergence in flag behavior would cause transactions to be accepted or rejected differently on DIG L2 compared to equivalent Chia L1 validation.

---

## Specification

### Flag Constants

```rust
/// Flags for controlling validation behavior.
/// These values MUST match chia-consensus definitions.

/// Enable MempoolVisitor for stricter CLVM execution.
/// Rejects unknown opcodes and enforces tighter cost rules.
/// L1 usage: mempool admission (mempool.py:13).
pub const MEMPOOL_MODE: u32 = 0x0001;

/// Skip BLS signature verification entirely.
/// L1 usage: mempool pre-validation (mempool.py:14).
pub const DONT_VALIDATE_SIGNATURE: u32 = 0x0004;
```

### Flag Combinations

```rust
/// All valid flag combinations and their use cases:

// 0x0000: Block validation mode (most permissive consensus rules)
// - BlockVisitor for CLVM execution
// - Full BLS signature verification
// - Used for validating blocks from the network
let block_validation = 0u32;

// 0x0001: Mempool admission mode (stricter rules)
// - MempoolVisitor for CLVM execution
// - Full BLS signature verification
// - Used for accepting transactions into the mempool
let mempool_admission = MEMPOOL_MODE;

// 0x0004: Block validation without signature check
// - BlockVisitor for CLVM execution
// - BLS signature verification skipped
// - Used for testing or signature-deferred validation
let block_no_sig = DONT_VALIDATE_SIGNATURE;

// 0x0005: Mempool pre-check without signature
// - MempoolVisitor for CLVM execution
// - BLS signature verification skipped
// - Used for quick mempool filtering before full validation
let mempool_prescan = MEMPOOL_MODE | DONT_VALIDATE_SIGNATURE;
```

### ValidationConfig Integration

```rust
pub struct ValidationConfig {
    /// Bitfield of validation flags.
    /// Combine flags with bitwise OR: MEMPOOL_MODE | DONT_VALIDATE_SIGNATURE
    pub flags: u32,
}

impl ValidationConfig {
    /// Block validation mode (default, most permissive).
    pub fn block_mode() -> Self {
        Self { flags: 0 }
    }

    /// Mempool admission mode (stricter CLVM rules).
    pub fn mempool_mode() -> Self {
        Self { flags: MEMPOOL_MODE }
    }

    /// Check if MEMPOOL_MODE is enabled.
    pub fn is_mempool_mode(&self) -> bool {
        self.flags & MEMPOOL_MODE != 0
    }

    /// Check if signature verification is disabled.
    pub fn skip_signature(&self) -> bool {
        self.flags & DONT_VALIDATE_SIGNATURE != 0
    }
}
```

### Flag Forwarding to chia-consensus

The flags are forwarded directly without modification:

```rust
// In validate_spend_bundle:
pub fn validate_spend_bundle(
    bundle: &SpendBundle,
    context: &ValidationContext,
    config: &ValidationConfig,
    cache: Option<&mut BlsCache>,
) -> Result<SpendResult, ValidationError> {
    // CLVM execution: flags determine visitor selection
    let conditions = run_puzzle(
        &mut allocator,
        &coin_spend.puzzle_reveal,
        &coin_spend.solution,
        config.flags,  // Forwarded directly to chia-consensus
        context.constants.consensus(),
    )?;

    // BLS verification: flag determines whether to skip
    if !config.skip_signature() {
        verify_bls_signature(bundle, &conditions, context.constants, cache)?;
    }

    // ...
}
```

### Flag Effect Matrix

| Flag Combination | CLVM Visitor | Unknown Opcodes | BLS Verification | Use Case |
|-----------------|-------------|-----------------|-----------------|----------|
| `0x0000` | BlockVisitor | Accepted (no-op) | Enabled | Block validation |
| `0x0001` (MEMPOOL_MODE) | MempoolVisitor | Rejected | Enabled | Mempool admission |
| `0x0004` (DONT_VALIDATE_SIG) | BlockVisitor | Accepted (no-op) | Skipped | Testing |
| `0x0005` (both) | MempoolVisitor | Rejected | Skipped | Mempool pre-check |

### L1 Parity Verification

```rust
#[test]
fn flag_values_match_l1() {
    // These values must match chia-consensus constants
    assert_eq!(MEMPOOL_MODE, 0x0001);
    assert_eq!(DONT_VALIDATE_SIGNATURE, 0x0004);

    // Verify they are distinct bits (combinable)
    assert_eq!(MEMPOOL_MODE & DONT_VALIDATE_SIGNATURE, 0);
}
```

---

## Acceptance Criteria

- [ ] `MEMPOOL_MODE` flag value is `0x0001`, matching the `chia-consensus` definition.
- [ ] `DONT_VALIDATE_SIGNATURE` flag value is `0x0004`, matching the `chia-consensus` definition.
- [ ] Flags are combinable via bitwise OR (`MEMPOOL_MODE | DONT_VALIDATE_SIGNATURE` = `0x0005`).
- [ ] `MEMPOOL_MODE` causes `chia-consensus` to use `MempoolVisitor` (stricter CLVM rules).
- [ ] `DONT_VALIDATE_SIGNATURE` causes BLS signature verification to be skipped entirely.
- [ ] Flag semantics are identical for both `validate_spend_bundle` and `validate_block`.

---

## Implementation Notes

- **Primary files:** `src/consensus/config.rs` (flag constants and ValidationConfig), `src/consensus/validate.rs` (flag checking and forwarding).
- **No custom flags:** `dig-clvm` should not define custom flag values that `chia-consensus` does not recognize. Custom flags would be silently ignored by `chia-consensus` or, worse, conflict with future flag definitions.
- **Flag extensibility:** The `u32` bitfield has room for 32 flags. Future flags from `chia-consensus` (e.g., for new soft fork features) should be re-exported by `dig-clvm` as they become available.
- **Thread safety:** Flag constants are `const u32` values — immutable and thread-safe by definition.
- **Default flags:** When no flags are specified (flags = 0), the behavior should match Chia L1's block validation mode: permissive CLVM rules with full BLS verification.
- **Flag in error messages:** When reporting validation errors, consider including the active flags in the error context so that failures can be correlated with the validation mode.
- **Both validation paths:** The same flags apply to both `validate_spend_bundle` and `validate_block`. The block validation path forwards flags to `run_block_generator2()` and to any per-bundle validation it performs internally.

---

## Verification

### Test Plan

| Test | Type | Description | Expected Result |
|------|------|-------------|-----------------|
| MEMPOOL_MODE value | Unit test | Assert MEMPOOL_MODE == 0x0001 | Match |
| DONT_VALIDATE_SIGNATURE value | Unit test | Assert DONT_VALIDATE_SIGNATURE == 0x0004 | Match |
| Flags combinable | Unit test | MEMPOOL_MODE \| DONT_VALIDATE_SIGNATURE == 0x0005 | No bit collision |
| Mempool rejects unknown opcode | Simulator test | Unknown opcode with MEMPOOL_MODE | Rejected |
| Block accepts unknown opcode | Simulator test | Same bundle without MEMPOOL_MODE | Accepted |
| Skip signature | Simulator test | Invalid sig with DONT_VALIDATE_SIGNATURE | Passes (sig not checked) |
| Combined: strict CLVM, no sig | Simulator test | Both flags set, unknown opcode | CLVM rejected (mempool), sig not checked |
| Same flags for block path | Integration test | Pass MEMPOOL_MODE to validate_block | Same strict behavior as validate_spend_bundle |

---

## Source Citations

- **SPEC.md Section 7**: "MEMPOOL_MODE enables MempoolVisitor (stricter). DONT_VALIDATE_SIGNATURE skips BLS. Combinable."
- **L1 reference — mempool.py:13:** [`mempool.py`](https://github.com/Chia-Network/chia-blockchain/blob/main/chia/full_node/mempool.py#L13) — MEMPOOL_MODE flag set during mempool validation.
- **L1 reference — mempool.py:14:** [`mempool.py`](https://github.com/Chia-Network/chia-blockchain/blob/main/chia/full_node/mempool.py#L14) — DONT_VALIDATE_SIGNATURE flag for pre-validation.
- **chia-consensus source:** Flag constant definitions matching 0x0001 and 0x0004.

---

## References

- [VAL-012](../../validation/specs/VAL-012.md) — BLS signature verification (controlled by DONT_VALIDATE_SIGNATURE)
- [VAL-013](../../validation/specs/VAL-013.md) — MEMPOOL_MODE stricter rules (detailed behavior)
- [PAR-010](PAR-010.md) — Block generator parity (flags forwarded to run_block_generator2)
- [BLK-008](../../block_generator/specs/BLK-008.md) — Same checks for blocks (flags apply identically)
