# PAR-005: Aggregate Signature Verification via chia-bls

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

---

## Summary

Aggregate BLS signature verification in `dig-clvm` must use `chia_bls::aggregate_verify()`, the same BLS12-381 implementation used by Chia L1 full nodes. BLS12-381 is the signature scheme used throughout the Chia ecosystem: every spend bundle contains an aggregated BLS signature that proves authorization for all coin spends in the bundle. The `aggregate_verify()` function takes a list of `(public_key, message)` pairs and a single aggregated signature, returning whether the signature is valid for all pairs simultaneously.

Using the same `chia-bls` implementation as Chia L1 ensures bit-for-bit identical verification behavior. BLS12-381 involves complex elliptic curve arithmetic (G1/G2 point operations, pairing computation, Miller loop), and even minor implementation differences (e.g., different point validation, different hash-to-curve, different pairing engine) could cause some signatures to verify differently. The `chia-bls` crate wraps the `blst` library, which is the de facto standard BLS12-381 implementation used by Ethereum 2.0, Chia, and other blockchain projects.

The `dig-clvm` crate must not implement its own BLS verification, wrap an alternative BLS library, or modify the verification behavior. All BLS types (`PublicKey`, `SecretKey`, `Signature`) must be re-exported from `chia-bls`. The `aggregate_verify()` function must be the sole entry point for aggregate signature verification. Individual signature verification via `verify()` may be used for testing but should not appear in production validation paths. This requirement works in conjunction with [PAR-004](PAR-004.md) (domain separation) and [BLS-004](../../bls_cache/specs/BLS-004.md) (`BlsCache` type).

---

## Specification

### Required API Usage

```rust
use chia_bls::{aggregate_verify, PublicKey, Signature};

/// Verify an aggregated BLS signature against multiple (pk, msg) pairs.
///
/// This is the core signature verification call used during validation.
/// It is called by chia-consensus internally, and dig-clvm delegates to it.
fn verify_aggregate_signature(
    pks: &[PublicKey],
    msgs: &[Vec<u8>],
    aggregated_sig: &Signature,
) -> bool {
    // Messages must be domain-separated per PAR-004
    aggregate_verify(aggregated_sig, pks.iter().zip(msgs.iter().map(|m| m.as_slice())))
}
```

### BLS12-381 Parameters

The `chia-bls` crate uses the following BLS12-381 parameters (matching Chia L1):

| Parameter | Value |
|-----------|-------|
| Curve | BLS12-381 |
| Signature scheme | Basic scheme (not augmented) with Chia domain separation |
| G1 | Public keys (48 bytes compressed) |
| G2 | Signatures (96 bytes compressed) |
| Hash-to-curve | As specified by the `blst` library |
| Aggregation | Signature aggregation via point addition on G2 |
| Verification | Multi-pairing check: `e(pk1, H(msg1)) * ... * e(pkn, H(msgn)) == e(G1, sig)` |

### Re-export Surface

```rust
// In dig-clvm's lib.rs:
pub use chia_bls::{PublicKey, SecretKey, Signature, aggregate_verify, BlsCache};
```

### Integration with Validation Pipeline

In the production validation path, `aggregate_verify()` is called by `chia-consensus` internally:

```rust
// validate_spend_bundle() delegates to chia-consensus, which:
// 1. Executes CLVM for each spend (PAR-001)
// 2. Parses conditions (PAR-002)
// 3. Constructs domain-separated messages (PAR-004)
// 4. Calls aggregate_verify() with all (pk, msg) pairs and the bundle's signature
//
// dig-clvm does NOT call aggregate_verify() directly in the production path.
// It is called by chia-consensus as part of run_spendbundle() or
// validate_clvm_and_signature().
```

### Prohibited Patterns

```rust
// PROHIBITED: Custom BLS implementation
fn bls_verify(pk: &[u8; 48], msg: &[u8], sig: &[u8; 96]) -> bool {
    // custom elliptic curve operations
}

// PROHIBITED: Alternative BLS library
use bls_signatures::verify;  // different library, different behavior

// PROHIBITED: Skipping verification
fn verify_signature(_pk: &PublicKey, _msg: &[u8], _sig: &Signature) -> bool {
    true  // always pass
}

// PROHIBITED: Individual verification in production path
for (pk, msg) in pairs {
    chia_bls::verify(&pk, &msg, &individual_sig)?;  // should use aggregate_verify
}
```

---

## Acceptance Criteria

- [ ] All BLS signature verification in the production path uses `chia_bls::aggregate_verify()` (via `chia-consensus`)
- [ ] No custom BLS verification code exists in `dig-clvm` (`grep -r "fn.*verify.*signature\|fn bls_verify" src/` returns zero production matches)
- [ ] `PublicKey`, `SecretKey`, `Signature`, and `aggregate_verify` are re-exported from the crate root
- [ ] A valid aggregated signature passes verification; a tampered signature fails
- [ ] The `chia-bls` dependency version matches the version used by `chia-consensus`

---

## Implementation Notes

- `aggregate_verify()` is O(n) in the number of pairings, where each pairing involves an expensive elliptic curve operation. This is the primary computational bottleneck in spend bundle validation.
- The `BlsCache` optimization (see [BLS-001](../../bls_cache/specs/BLS-001.md)) amortizes this cost by caching verified pairings.
- `aggregate_verify()` returns `false` (not an error) for invalid signatures. The caller must convert this to a `ValidationError`.
- The `blst` library (underlying `chia-bls`) is written in C and assembly for performance. It is a well-audited, production-grade implementation.
- For testing, `chia_bls::sign()` is used to create signatures, and `chia_bls::aggregate()` to combine them. These must also come from `chia-bls`.

---

## Verification

### Test Plan

1. **Valid signature verification**:
   - Generate a key pair using `chia_bls::SecretKey::from_seed()`.
   - Sign a message using `chia_bls::sign()`.
   - Verify using `chia_bls::aggregate_verify()` with one pair.
   - Assert returns `true`.

2. **Invalid signature rejection**:
   - Take the valid signature from test 1.
   - Tamper with one byte of the signature.
   - Attempt `aggregate_verify()`.
   - Assert returns `false`.

3. **Multi-pair aggregation**:
   - Generate 3 key pairs and sign 3 different messages.
   - Aggregate the 3 signatures using `chia_bls::aggregate()`.
   - Call `aggregate_verify()` with all 3 `(pk, msg)` pairs and the aggregated signature.
   - Assert returns `true`.

4. **Wrong message rejection**:
   - Using the aggregated setup from test 3, replace one message with a different value.
   - Assert `aggregate_verify()` returns `false`.

5. **End-to-end bundle verification**:
   - Build a `SpendBundle` using `Simulator` with auto-signing.
   - Call `validate_spend_bundle()`.
   - Assert success (BLS verification passed internally).
   - Tamper with `bundle.aggregated_signature`.
   - Call `validate_spend_bundle()` again.
   - Assert `Err(ValidationError::InvalidSignature(..))`.

6. **Code review -- no custom BLS**:
   - Run `grep -rn "fn.*verify\|fn.*pairing\|fn.*bls" src/`.
   - Verify no custom BLS implementation exists.
   - Verify all BLS operations trace back to `chia-bls`.

### Expected Test Files

- `tests/signature_tests.rs` -- PAR-005 BLS verification tests
- `tests/validation_tests.rs` -- end-to-end bundle signature verification

---

## Source Citations

- Chia L1 BLS usage: [`condition_tools.py:74-100`](https://github.com/Chia-Network/chia-blockchain/blob/main/chia/consensus/condition_tools.py#L74)
- `chia-bls` crate: [`chia-bls` v0.26](https://crates.io/crates/chia-bls)
- `blst` library: [supranational/blst](https://github.com/supranational/blst)
- dig-clvm BLS re-exports: [SPEC.md Section 3.2](../../../../resources/SPEC.md)

---

## References

- [PAR-004](PAR-004.md) -- BLS domain separation (constructs the messages verified here)
- [BLS-001](../../bls_cache/specs/BLS-001.md) -- BlsCache parameter (caches results of `aggregate_verify()`)
- [BLS-004](../../bls_cache/specs/BLS-004.md) -- Uses `chia-bls::BlsCache` directly (same crate)
- [BLS-005](../../bls_cache/specs/BLS-005.md) -- Cache does not affect correctness (verification outcome is deterministic)
