Skip to main content

nodedb_types/
wire_version.rs

1// SPDX-License-Identifier: Apache-2.0
2
3//! Single source of truth for the `WIRE_FORMAT_VERSION` constant and the
4//! `WIRE_BUILD_ID` build identity, shared between every crate that needs to
5//! stamp or interpret them.
6//!
7//! `WIRE_FORMAT_VERSION` is the *cluster-wide* wire format version, distinct
8//! from:
9//! - `nodedb_cluster::wire::WIRE_VERSION` (the binary frame layout
10//!   version of the `VShardEnvelope`),
11//! - the RPC frame header version in
12//!   `nodedb_cluster::rpc_codec::header` (a private constant of that
13//!   module).
14//!
15//! # The enforced invariant before 1.0: exact build identity
16//!
17//! `WIRE_FORMAT_VERSION` stays at `1` until the first stable release — see
18//! below for why a bump buys nothing pre-1.0. That leaves a hole: two builds
19//! can change wire shapes (a new enum variant, an RPC field) without
20//! touching this constant, so a version-only check lets them join the same
21//! cluster and misdecode each other. `WIRE_BUILD_ID` closes it: every join
22//! and every wire-version handshake also compares this value for exact
23//! equality, so a cluster can only ever contain nodes running one build.
24//!
25//! `WIRE_BUILD_ID` is the current commit's short git hash, or
26//! `CARGO_PKG_VERSION` when git is unavailable (a crates.io build) — see
27//! `build.rs`. It intentionally excludes dirty-tree state: hashing local
28//! edits would force a rebuild of every dependent crate on every save.
29//!
30//! # DO NOT BUMP `WIRE_FORMAT_VERSION` BEFORE 1.0
31//!
32//! Read this before changing it — the reflex to bump on any wire-shape
33//! change is wrong here:
34//!
35//! - **There is nothing to be compatible with.** Pre-1.0 there are no
36//!   deployed clusters, so there is no older peer a new build must talk to.
37//! - **A bump cannot buy a rolling upgrade.** `MIN_WIRE_FORMAT_VERSION ==
38//!   WIRE_FORMAT_VERSION` (floor == ceiling), so a node rejects *any* peer
39//!   whose version differs. Mixed-version clusters cannot form at all, which
40//!   makes every `wire_version >= V` feature gate dead code: inside a cluster
41//!   that exists, all nodes are provably on this exact version. Adding such a
42//!   gate is unreachable-branch hardening, not safety.
43//! - **This value is NOT persisted.** It is stamped on `NodeInfo` for the
44//!   handshake and drives `ClusterVersionView`, nothing more. The version
45//!   written into stored raft-log and metadata entries is
46//!   `nodedb_cluster::wire_version::WireVersion::CURRENT`, which is separate
47//!   and independent. Changing the constant here therefore cannot orphan or
48//!   corrupt anything already on disk.
49//!
50//! So: adding a new enum variant, RPC, or payload field needs NO bump.
51//! `WIRE_BUILD_ID` already forces every node in a working cluster onto the
52//! same build. Ratcheting this pre-1.0 only invents a stop-the-world upgrade
53//! requirement that does not otherwise exist, and would leave 1.0 shipping
54//! as "wire version 20" for no reason.
55//!
56//! After 1.0, when real deployments exist and a genuine compatibility window
57//! is introduced, this becomes meaningful — bump it then, deliberately, and
58//! only alongside an actual `MIN_WIRE_FORMAT_VERSION < WIRE_FORMAT_VERSION`
59//! support window.
60
61/// Cluster-wide wire format version. Stamped on every `NodeInfo` and
62/// returned by `nodedb::version::WIRE_FORMAT_VERSION` (a re-export).
63///
64/// WARNING: pinned at 1 until 1.0. See the module docs above before changing.
65pub const WIRE_FORMAT_VERSION: u16 = 1;
66
67/// Minimum wire format version this build can read. Equal to
68/// `WIRE_FORMAT_VERSION`: floor == ceiling, no backward compat window.
69pub const MIN_WIRE_FORMAT_VERSION: u16 = WIRE_FORMAT_VERSION;
70
71/// This build's exact identity: the short git commit hash, or
72/// `CARGO_PKG_VERSION` when git is unavailable (a crates.io build). Set by
73/// `build.rs`.
74///
75/// Compared for exact equality on every join and wire-version handshake —
76/// the enforced invariant before 1.0. See the module docs above.
77pub const WIRE_BUILD_ID: &str = env!("NODEDB_WIRE_BUILD_ID");
78
79// Compile-time invariants — these constants must satisfy:
80//   - MIN_WIRE_FORMAT_VERSION <= WIRE_FORMAT_VERSION
81//   - WIRE_FORMAT_VERSION > 0
82const _: () = assert!(MIN_WIRE_FORMAT_VERSION <= WIRE_FORMAT_VERSION);
83const _: () = assert!(WIRE_FORMAT_VERSION > 0);
84
85#[cfg(test)]
86mod tests {
87    use super::*;
88
89    #[test]
90    fn wire_build_id_is_non_empty() {
91        assert!(!WIRE_BUILD_ID.is_empty(), "WIRE_BUILD_ID must not be empty");
92    }
93}