sphinx_packet/
version.rs

1// Copyright 2025 Nym Technologies SA
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15// in the old versions of the sphinx crate we've been attempting to use semver information
16// reduced to 3 bytes, where [0, 1, 0] and [0, 1, 1] have already been released.
17// therefore those are our starting point for further versioning
18
19use crate::constants::VERSION_LENGTH;
20
21pub const INITIAL_LEGACY_VERSION: Version = Version(1);
22pub const UPDATED_LEGACY_VERSION: Version = Version(257);
23pub const X25519_WITH_EXPLICIT_PAYLOAD_KEYS_VERSION: Version = Version(258);
24pub const PAYLOAD_KEYS_SEEDS_VERSION: Version = Version(259);
25
26pub const CURRENT_VERSION: Version = PAYLOAD_KEYS_SEEDS_VERSION;
27
28pub const KNOWN_VERSIONS: &[Version] = &[
29    INITIAL_LEGACY_VERSION,
30    UPDATED_LEGACY_VERSION,
31    X25519_WITH_EXPLICIT_PAYLOAD_KEYS_VERSION,
32    PAYLOAD_KEYS_SEEDS_VERSION,
33];
34
35#[derive(Debug, Copy, Clone, PartialEq)]
36pub struct Version(pub u16);
37
38impl Version {
39    pub fn new(value: u16) -> Version {
40        Version(value)
41    }
42
43    pub fn value(&self) -> u16 {
44        self.0
45    }
46
47    pub fn is_legacy(&self) -> bool {
48        self == &INITIAL_LEGACY_VERSION || self == &UPDATED_LEGACY_VERSION
49    }
50
51    // as opposed to using payload key seed to derive the keys
52    pub fn expects_legacy_full_payload_keys(&self) -> bool {
53        self.is_legacy() || self == &X25519_WITH_EXPLICIT_PAYLOAD_KEYS_VERSION
54    }
55
56    // extra byte comes from the legacy interpretation
57    pub fn from_bytes(bytes: [u8; VERSION_LENGTH]) -> Version {
58        debug_assert_eq!(bytes[0], 0);
59        Version(u16::from_be_bytes([bytes[1], bytes[2]]))
60    }
61
62    pub fn to_bytes(self) -> [u8; VERSION_LENGTH] {
63        let b = self.0.to_be_bytes();
64        [0, b[0], b[1]]
65    }
66}
67
68impl Default for Version {
69    fn default() -> Self {
70        CURRENT_VERSION
71    }
72}