platform_version/version/
protocol_version.rs

1use crate::error::PlatformVersionError;
2use crate::version::dpp_versions::DPPVersion;
3use crate::version::drive_abci_versions::DriveAbciVersion;
4use crate::version::drive_versions::DriveVersion;
5use crate::version::fee::FeeVersion;
6#[cfg(feature = "mock-versions")]
7use crate::version::mocks::v2_test::TEST_PLATFORM_V2;
8#[cfg(feature = "mock-versions")]
9use crate::version::mocks::v3_test::TEST_PLATFORM_V3;
10#[cfg(feature = "mock-versions")]
11use crate::version::mocks::TEST_PROTOCOL_VERSION_SHIFT_BYTES;
12use crate::version::system_data_contract_versions::SystemDataContractVersions;
13#[cfg(feature = "mock-versions")]
14use std::sync::OnceLock;
15
16use crate::version::consensus_versions::ConsensusVersions;
17use crate::version::system_limits::SystemLimits;
18
19use crate::version::v1::PLATFORM_V1;
20use crate::version::v10::PLATFORM_V10;
21use crate::version::v11::PLATFORM_V11;
22use crate::version::v12::PLATFORM_V12;
23use crate::version::v2::PLATFORM_V2;
24use crate::version::v3::PLATFORM_V3;
25use crate::version::v4::PLATFORM_V4;
26use crate::version::v5::PLATFORM_V5;
27use crate::version::v6::PLATFORM_V6;
28use crate::version::v7::PLATFORM_V7;
29use crate::version::v8::PLATFORM_V8;
30use crate::version::v9::PLATFORM_V9;
31
32use crate::version::ProtocolVersion;
33pub use versioned_feature_core::*;
34
35#[derive(Clone, Debug)]
36pub struct PlatformVersion {
37    pub protocol_version: ProtocolVersion,
38    pub dpp: DPPVersion,
39    pub drive: DriveVersion,
40    pub drive_abci: DriveAbciVersion,
41    pub consensus: ConsensusVersions,
42    pub fee_version: FeeVersion,
43    pub system_data_contracts: SystemDataContractVersions,
44    pub system_limits: SystemLimits,
45}
46
47pub const PLATFORM_VERSIONS: &[PlatformVersion] = &[
48    PLATFORM_V1,
49    PLATFORM_V2,
50    PLATFORM_V3,
51    PLATFORM_V4,
52    PLATFORM_V5,
53    PLATFORM_V6,
54    PLATFORM_V7,
55    PLATFORM_V8,
56    PLATFORM_V9,
57    PLATFORM_V10,
58    PLATFORM_V11,
59    PLATFORM_V12,
60];
61
62#[cfg(feature = "mock-versions")]
63// We use OnceLock to be able to modify the version mocks
64pub static PLATFORM_TEST_VERSIONS: OnceLock<Vec<PlatformVersion>> = OnceLock::new();
65#[cfg(feature = "mock-versions")]
66const DEFAULT_PLATFORM_TEST_VERSIONS: &[PlatformVersion] = &[TEST_PLATFORM_V2, TEST_PLATFORM_V3];
67
68pub const LATEST_PLATFORM_VERSION: &PlatformVersion = &PLATFORM_V12;
69
70pub const DESIRED_PLATFORM_VERSION: &PlatformVersion = LATEST_PLATFORM_VERSION;
71
72impl PlatformVersion {
73    pub fn get<'a>(version: ProtocolVersion) -> Result<&'a Self, PlatformVersionError> {
74        if version > 0 {
75            #[cfg(feature = "mock-versions")]
76            {
77                if version >> TEST_PROTOCOL_VERSION_SHIFT_BYTES > 0 {
78                    let test_version = version - (1 << TEST_PROTOCOL_VERSION_SHIFT_BYTES);
79
80                    // Init default set of test versions
81                    let versions = PLATFORM_TEST_VERSIONS
82                        .get_or_init(|| vec![TEST_PLATFORM_V2, TEST_PLATFORM_V3]);
83
84                    return versions.get(test_version as usize - 2).ok_or(
85                        PlatformVersionError::UnknownVersionError(format!(
86                            "no test platform version {test_version}"
87                        )),
88                    );
89                }
90            }
91            PLATFORM_VERSIONS.get(version as usize - 1).ok_or_else(|| {
92                PlatformVersionError::UnknownVersionError(format!("no platform version {version}"))
93            })
94        } else {
95            Err(PlatformVersionError::UnknownVersionError(format!(
96                "no platform version {version}"
97            )))
98        }
99    }
100
101    pub fn get_optional<'a>(version: ProtocolVersion) -> Option<&'a Self> {
102        if version > 0 {
103            #[cfg(feature = "mock-versions")]
104            {
105                if version >> TEST_PROTOCOL_VERSION_SHIFT_BYTES > 0 {
106                    let test_version = version - (1 << TEST_PROTOCOL_VERSION_SHIFT_BYTES);
107
108                    // Init default set of test versions
109                    let versions = PLATFORM_TEST_VERSIONS
110                        .get_or_init(|| vec![TEST_PLATFORM_V2, TEST_PLATFORM_V3]);
111
112                    return versions.get(test_version as usize - 2);
113                }
114            }
115            PLATFORM_VERSIONS.get(version as usize - 1)
116        } else {
117            None
118        }
119    }
120
121    pub fn get_version_or_latest<'a>(
122        version: Option<ProtocolVersion>,
123    ) -> Result<&'a Self, PlatformVersionError> {
124        if let Some(version) = version {
125            if version > 0 {
126                #[cfg(feature = "mock-versions")]
127                {
128                    if version >> TEST_PROTOCOL_VERSION_SHIFT_BYTES > 0 {
129                        let test_version = version - (1 << TEST_PROTOCOL_VERSION_SHIFT_BYTES);
130
131                        // Init default set of test versions
132                        let versions = PLATFORM_TEST_VERSIONS
133                            .get_or_init(|| Vec::from(DEFAULT_PLATFORM_TEST_VERSIONS));
134
135                        return versions.get(test_version as usize - 2).ok_or(
136                            PlatformVersionError::UnknownVersionError(format!(
137                                "no test platform version {test_version}"
138                            )),
139                        );
140                    }
141                }
142                PLATFORM_VERSIONS.get(version as usize - 1).ok_or(
143                    PlatformVersionError::UnknownVersionError(format!(
144                        "no platform version {version}"
145                    )),
146                )
147            } else {
148                Err(PlatformVersionError::UnknownVersionError(format!(
149                    "no platform version {version}"
150                )))
151            }
152        } else {
153            Ok(Self::latest())
154        }
155    }
156
157    pub fn first<'a>() -> &'a Self {
158        PLATFORM_VERSIONS
159            .first()
160            .expect("expected to have a platform version")
161    }
162
163    pub fn latest<'a>() -> &'a Self {
164        PLATFORM_VERSIONS
165            .last()
166            .expect("expected to have a platform version")
167    }
168
169    pub fn desired<'a>() -> &'a Self {
170        DESIRED_PLATFORM_VERSION
171    }
172
173    #[cfg(feature = "mock-versions")]
174    /// Set mock versions for testing
175    pub fn replace_test_versions(versions: Vec<PlatformVersion>) {
176        PLATFORM_TEST_VERSIONS
177            .set(versions)
178            .expect("failed to set test versions")
179    }
180}