Skip to main content

iota_types/
supported_protocol_versions.rs

1// Copyright (c) Mysten Labs, Inc.
2// Modifications Copyright (c) 2024 IOTA Stiftung
3// SPDX-License-Identifier: Apache-2.0
4
5use std::ops::RangeInclusive;
6
7use fastcrypto::hash::HashFunction;
8pub use iota_protocol_config::{Chain, ProtocolConfig, ProtocolVersion};
9use iota_sdk_types::Digest;
10use serde::{Deserialize, Serialize};
11
12use crate::crypto::DefaultHash;
13
14/// Models the set of protocol versions supported by a validator.
15/// The `iota-node` binary will always use the SYSTEM_DEFAULT constant, but for
16/// testing we need to be able to inject arbitrary versions into IotaNode.
17#[derive(Serialize, Deserialize, Debug, Clone, Copy, Hash, PartialEq, Eq)]
18pub struct SupportedProtocolVersions {
19    pub min: ProtocolVersion,
20    pub max: ProtocolVersion,
21}
22
23impl SupportedProtocolVersions {
24    pub const SYSTEM_DEFAULT: Self = Self {
25        min: ProtocolVersion::MIN,
26        max: ProtocolVersion::MAX,
27    };
28
29    pub fn new_for_testing(min: u64, max: u64) -> Self {
30        let min = min.into();
31        let max = max.into();
32        Self { min, max }
33    }
34
35    pub fn is_version_supported(&self, v: ProtocolVersion) -> bool {
36        v.as_u64() >= self.min.as_u64() && v.as_u64() <= self.max.as_u64()
37    }
38
39    pub fn as_range(&self) -> RangeInclusive<u64> {
40        self.min.as_u64()..=self.max.as_u64()
41    }
42
43    pub fn truncate_below(self, v: ProtocolVersion) -> Self {
44        let min = std::cmp::max(self.min, v);
45        Self { min, max: self.max }
46    }
47}
48
49/// Models the set of protocol versions supported by a validator.
50/// The `iota-node` binary will always use the SYSTEM_DEFAULT constant, but for
51/// testing we need to be able to inject arbitrary versions into IotaNode.
52#[derive(Serialize, Deserialize, Debug, Clone, Hash, PartialEq, Eq)]
53pub struct SupportedProtocolVersionsWithHashes {
54    pub versions: Vec<(ProtocolVersion, Digest)>,
55}
56
57impl SupportedProtocolVersionsWithHashes {
58    pub fn get_version_digest(&self, v: ProtocolVersion) -> Option<Digest> {
59        self.versions
60            .iter()
61            .find(|(version, _)| *version == v)
62            .map(|(_, digest)| *digest)
63    }
64
65    // Ideally this would be in iota-protocol-config, but iota-types depends on
66    // iota-protocol-config, so it would introduce a circular dependency.
67    pub fn protocol_config_digest(config: &ProtocolConfig) -> Digest {
68        let mut digest = DefaultHash::default();
69        bcs::serialize_into(&mut digest, &config).expect("serialization cannot fail");
70        Digest::new(digest.finalize().into())
71    }
72
73    pub fn from_supported_versions(supported: SupportedProtocolVersions, chain: Chain) -> Self {
74        Self {
75            versions: supported
76                .as_range()
77                .map(|v| {
78                    (
79                        v.into(),
80                        Self::protocol_config_digest(&ProtocolConfig::get_for_version(
81                            v.into(),
82                            chain,
83                        )),
84                    )
85                })
86                .collect(),
87        }
88    }
89}