# TYP-005: StoredCheckpoint Struct

| Link | Path |
|------|------|
| **Normative** | [NORMATIVE.md](../NORMATIVE.md) |
| **Verification** | [VERIFICATION.md](../VERIFICATION.md) |
| **Tracking** | [TRACKING.yaml](../TRACKING.yaml) |
| **Spec** | [SPEC.md](../../../../resources/SPEC.md) Section 3.3 |

---

## Summary

StoredCheckpoint wraps a Checkpoint with its attestation proof data and storage metadata for persistence in CF_CHECKPOINTS.

---

## Specification

```rust
use chia_bls::{PublicKey, Signature};
use chia_protocol::Bytes32;
use dig_block::{Checkpoint, SignerBitmap};
use serde::{Deserialize, Serialize};

/// A checkpoint with its attestation proof, stored in CF_CHECKPOINTS.
/// Keyed by epoch number (big-endian u64).
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StoredCheckpoint {
    /// The checkpoint data (epoch, block hash, state root, etc.)
    pub checkpoint: Checkpoint,

    /// Bitmap indicating which signers contributed to the aggregate signature.
    pub signer_bitmap: SignerBitmap,

    /// BLS aggregate signature over the checkpoint.
    pub aggregate_signature: Signature,

    /// BLS aggregate public key of the signers.
    pub aggregate_pubkey: PublicKey,

    /// Attestation score (number of signers or weighted vote).
    pub score: u64,

    /// Index of the validator that submitted this checkpoint.
    pub submitter: u32,

    /// L1 block height where this checkpoint was anchored (if confirmed).
    pub l1_height: Option<u32>,

    /// L1 coin ID associated with the checkpoint submission (if confirmed).
    pub l1_coin_id: Option<Bytes32>,

    /// Unix timestamp when this checkpoint was stored locally.
    pub stored_at: u64,
}
```

### Serialization

StoredCheckpoint is serialized using bincode for storage in CF_CHECKPOINTS. The key is the epoch number encoded as an 8-byte big-endian u64 (for natural sort order by epoch).

### Field Details

| Field | Type | Description |
|-------|------|-------------|
| `checkpoint` | `Checkpoint` | Core checkpoint data from dig-block |
| `signer_bitmap` | `SignerBitmap` | Bit vector of contributing signers |
| `aggregate_signature` | `Signature` | BLS aggregate signature (96 bytes) |
| `aggregate_pubkey` | `PublicKey` | BLS aggregate public key (48 bytes) |
| `score` | `u64` | Attestation score |
| `submitter` | `u32` | Submitting validator index |
| `l1_height` | `Option<u32>` | L1 confirmation height |
| `l1_coin_id` | `Option<Bytes32>` | L1 coin ID for on-chain anchor |
| `stored_at` | `u64` | Local storage timestamp |

---

## Acceptance Criteria

- [x] `StoredCheckpoint` has all 9 fields as specified
- [x] `StoredCheckpoint` derives `Debug`, `Clone`, `Serialize`, `Deserialize` (and `PartialEq`/`Eq` for test assertions)
- [x] `checkpoint` field uses the `Checkpoint` type from dig-block
- [x] `signer_bitmap` field uses `SignerBitmap` from dig-block
- [x] `aggregate_signature` field uses `Signature` from chia-bls
- [x] `aggregate_pubkey` field uses `PublicKey` from chia-bls
- [x] `l1_height` and `l1_coin_id` are `Option` types
- [x] Bincode serialization round-trip preserves all fields
- [x] Can be stored and retrieved from CF_CHECKPOINTS

---

## Implementation Notes

- Define in `src/types/stored_checkpoint.rs`.
- `Checkpoint` and `SignerBitmap` come from the dig-block crate.
- `Signature` and `PublicKey` come from the chia-bls crate (`features = ["serde"]` in `Cargo.toml` for bincode).
- Serde `Serialize`/`Deserialize` are needed for bincode serialization.
- The `stored_at` field uses a Unix timestamp (seconds since epoch).
- **`Checkpoint` wire shape:** Defined in the `dig-block` crate (CKP-001: `epoch`, roots, counts, fees) — `StoredCheckpoint` embeds that type verbatim; do not duplicate fields in `dig-blockstore`.

---

## Test Plan

| Test Name | Type | Description |
|-----------|------|-------------|
| `test_stored_checkpoint_all_fields` | unit | Construct with all fields, verify each field accessor |
| `test_stored_checkpoint_bincode_roundtrip` | unit | Serialize to bincode, deserialize, assert equality |
| `test_stored_checkpoint_optional_none` | unit | Construct with l1_height=None and l1_coin_id=None, roundtrip |
| `test_stored_checkpoint_optional_some` | unit | Construct with l1_height=Some and l1_coin_id=Some, roundtrip |
| `test_stored_checkpoint_clone` | unit | Clone and verify field equality |
| `test_stored_checkpoint_debug` | unit | Format with `{:?}`, verify no panic |
| `test_stored_checkpoint_cf_checkpoints_roundtrip` | integration | RocksDB `put_cf`/`get_cf` on `CF_CHECKPOINTS` with `epoch_key` |

---

## Expected Test Files

- `tests/typ_005_tests.rs`
