Files
fips/core/Cargo.toml
Johnathan Corgan f89447d7ee Move link rekeys onto the rekey state machine
Every link peer's rekey now runs in its own rekey machine. The machine
holds the link's current, pending and previous sessions with their
indices and key-epoch bits, the drain, the peer's startup epoch, the
dampening, the link's age and the record of answered msg1s, and decides
every rekey step; the link handlers carry out what it decides. The
deployed link rules are gone, and tests fail if one of them comes back.
Nothing on the wire changes. What a peer or an operator can see:

- Retire a still-draining session before a link cutover demotes the
  current one.
- End an unanswered link rekey at 30 s and back off before the next.
- Recognise link msg1 copies by their ephemeral, keep refusals and the
  record across re-peering, and hold own rekeys past 31 s.
- Prompt the peer at a link rekey cutover and take the new key-epoch bit
  from the peer's.
- Keep a link's previous session until the peer is seen to move, and
  count its frames for liveness.
- Reset what a link holds for a peer when its rekey reveals the peer
  restarted.
- Treat a dial whose msg2 shows a new startup epoch as the peer's
  restart.
- Close the link rekey machine at a cross-connection move and build a
  new one on the winning session.
- Send the bloom filter again after every link rekey this node answers.
- Move to the later dial's session when a peer answers a second dial of
  ours.



The core's slow test suites, the models of the deployed releases and the
guard-switch meta-test, compile only with fips-core's slow-tests feature.
GitHub CI's Linux job runs them on every push and lints them alongside the
core's other clippy passes; local CI runs them with --slow-tests. Every other
platform's test run skips them, and fips-core is built at opt-level 2 for dev
and test builds, which brings the core's ordinary test run from about 210 s to
30 s. A link setup test backdates a pending by 150 s rather than an hour, since
an Instant on Windows cannot go back past the host's boot.
2026-10-20 16:26:00 +00:00

85 lines
4.4 KiB
TOML

[package]
name = "fips-core"
# Versioned with the workspace's root package: this crate is not published on
# its own, and its version here is never bumped. Release version bumps edit the
# root Cargo.toml only.
version = "0.0.0"
edition = "2024"
license = "MIT"
publish = false
[dependencies]
# `alloc` only on secp256k1, bech32 and hex: their `std` features would link
# `std`, which the bare-metal build (testing/build-core-baremetal.sh) rejects.
# Without `rand`, `Secp256k1::new()` does not blind the context; the host
# blinds it through `identity::init_secp`.
secp256k1 = { version = "0.30", default-features = false, features = ["alloc"] }
bech32 = { version = "0.12", default-features = false, features = ["alloc"] }
hex = { version = "0.4", default-features = false, features = ["alloc"] }
# The `zeroize` features clear the SHA-256 and HMAC states on drop, which hold
# handshake secrets in `noise`. `hmac`'s feature only forwards to `digest`'s,
# which `sha2`'s also turns on; it is listed so the HMAC inside `hkdf` keeps it
# if `sha2`'s ever stops doing so.
sha2 = { version = "0.11", default-features = false, features = ["zeroize"] }
hkdf = { version = "0.13", default-features = false }
hmac = { version = "0.13", default-features = false, features = ["zeroize"] }
# `alloc` for the `Zeroizing<Vec<u8>>` guards in the secret key decoding;
# `zeroize_derive` for the Noise cipher and symmetric states.
zeroize = { version = "1.9", default-features = false, features = ["alloc", "zeroize_derive"] }
thiserror = { version = "2.0", default-features = false }
once_cell = { version = "1.21", default-features = false, features = ["race", "alloc"] }
# `MmpMode` derives Serialize and Deserialize for the node configuration.
# Builds without `std` or `alloc`.
serde = { version = "1.0", default-features = false, features = ["derive"] }
# `log` for the bloom false-positive estimate: `core` has no float logarithm.
# Default features (`arch`) as the root crate had them, so the implementation
# the estimate uses does not change.
libm = "0.2"
# The hash map for peer-chosen keys (`utils::hash`): `hashbrown`'s table with a
# SipHash-1-3 hasher keyed from the host, as `std`'s `HashMap` is built. No
# default hasher: `foldhash` is not keyed on targets without address-space
# randomization.
hashbrown = { version = "0.16", default-features = false }
siphasher = { version = "1.0", default-features = false }
# The AEAD backend that builds for every target (`noise::aead`).
chacha20poly1305 = { version = "0.10", default-features = false }
# The hosted AEAD backend, behind the `ring` feature: its assembly is faster,
# but it does not build for bare-metal targets. The AEAD needs neither of its
# defaults (`alloc`, `dev_urandom_fallback`).
ring = { version = "0.17", default-features = false, optional = true }
[features]
# Use `ring` for the AEAD instead of RustCrypto (`noise::aead::AeadKey`).
# Hosted builds turn it on; bare-metal builds must leave it off.
ring = ["dep:ring"]
# Test hooks in `proto`, `cache`, `noise` and `node`: methods and re-exports that
# only unit tests use to set up or inspect state. This crate's tests see them
# through `cfg(test)`; the root crate's tests see them because the root
# enables this feature from its `[dev-dependencies]` only. Never enable it
# outside tests.
test-hooks = []
# The slow rekey test suites: the models of the deployed 0.5.x releases
# (`proto/rekey/tests/legacy`) and the guard-switch meta-test
# (`proto/rekey/tests/faults.rs`), which re-runs other tests under every fault
# switch. Off by default so every platform's test run skips them; GitHub CI's
# Linux job and local CI with --slow-tests turn it on, and the core's clippy
# passes lint the code it gates either way.
slow-tests = []
[dev-dependencies]
# Host-only test dependencies; tests may use `std`.
# Random keys for the test fixtures (`testutil::make_keypair`, the lookup
# tests) and the random source `testutil::TestEntropy`.
rand = "0.10.1"
# `sign_schnorr` for the protocol tests' signing fixtures, which secp256k1
# provides only with `rand` and `std`. Tests only: the library stays on
# `alloc`.
secp256k1 = { version = "0.30", default-features = false, features = ["rand", "std"] }
# `MmpMode`'s configuration spelling, checked with the parser the node
# configuration uses.
serde_yaml = "0.9"
# `serde_json::to_value` for the stats history's JSON form of a gap (NaN as
# `null`), as the control API serializes it.
serde_json = "1.0"