Problem:
l1/types/src/chain_block_metadata.rs derives BorshSerialize/BorshDeserialize on ChainBlockMetadata with no version field. Borsh encodes structs positionally, so:
- Adding a field silently breaks deserialization of any previously persisted bytes.
- Reordering fields silently changes the wire format with no detection.
This matters because consumers persist these checkpoints across restarts (the bridge expects config.root / config.tip to be supplied as Checkpoint after a process restart, and the natural way to do that is to serialize with borsh). Once data is in the wild, schema evolution becomes a migration problem.
Options to consider:
- Prepend a version: u8 field and gate decoding on the supported set. Cheapest forward-compat option.
- Document the type as wire-stable append-only (// borsh order is wire-stable, append-only - never reorder, only append) and accept that schema changes require an explicit migration.
- Wrap in a versioned envelope (enum ChainBlockMetadataV { V1(...) }) to give explicit per-version codecs.
Decide before any consumer persists ChainBlockMetadata bytes - afterwards is a migration.
Related: review pass on l1/types/src/chain_block_metadata.rs noted that field order is currently interleaved (header-derived / parent-derived / lane-state). Reordering would aid readability but is wire-breaking; bundling a reorder with the versioning decision is natural.
Problem:
l1/types/src/chain_block_metadata.rs derives BorshSerialize/BorshDeserialize on ChainBlockMetadata with no version field. Borsh encodes structs positionally, so:
This matters because consumers persist these checkpoints across restarts (the bridge expects config.root / config.tip to be supplied as Checkpoint after a process restart, and the natural way to do that is to serialize with borsh). Once data is in the wild, schema evolution becomes a migration problem.
Options to consider:
Decide before any consumer persists ChainBlockMetadata bytes - afterwards is a migration.
Related: review pass on l1/types/src/chain_block_metadata.rs noted that field order is currently interleaved (header-derived / parent-derived / lane-state). Reordering would aid readability but is wire-breaking; bundling a reorder with the versioning decision is natural.