platform_version/version/
protocol_version.rs1use 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::v13::PLATFORM_V13;
24use crate::version::v2::PLATFORM_V2;
25use crate::version::v3::PLATFORM_V3;
26use crate::version::v4::PLATFORM_V4;
27use crate::version::v5::PLATFORM_V5;
28use crate::version::v6::PLATFORM_V6;
29use crate::version::v7::PLATFORM_V7;
30use crate::version::v8::PLATFORM_V8;
31use crate::version::v9::PLATFORM_V9;
32
33use crate::version::ProtocolVersion;
34pub use versioned_feature_core::*;
35
36#[derive(Clone, Debug)]
37pub struct PlatformVersion {
38 pub protocol_version: ProtocolVersion,
39 pub dpp: DPPVersion,
40 pub drive: DriveVersion,
41 pub drive_abci: DriveAbciVersion,
42 pub consensus: ConsensusVersions,
43 pub fee_version: FeeVersion,
44 pub system_data_contracts: SystemDataContractVersions,
45 pub system_limits: SystemLimits,
46}
47
48pub const PLATFORM_VERSIONS: &[PlatformVersion] = &[
49 PLATFORM_V1,
50 PLATFORM_V2,
51 PLATFORM_V3,
52 PLATFORM_V4,
53 PLATFORM_V5,
54 PLATFORM_V6,
55 PLATFORM_V7,
56 PLATFORM_V8,
57 PLATFORM_V9,
58 PLATFORM_V10,
59 PLATFORM_V11,
60 PLATFORM_V12,
61 PLATFORM_V13,
62];
63
64#[cfg(feature = "mock-versions")]
65pub static PLATFORM_TEST_VERSIONS: OnceLock<Vec<PlatformVersion>> = OnceLock::new();
67#[cfg(feature = "mock-versions")]
68const DEFAULT_PLATFORM_TEST_VERSIONS: &[PlatformVersion] = &[TEST_PLATFORM_V2, TEST_PLATFORM_V3];
69
70pub const LATEST_PLATFORM_VERSION: &PlatformVersion = &PLATFORM_V13;
71
72pub const DESIRED_PLATFORM_VERSION: &PlatformVersion = LATEST_PLATFORM_VERSION;
73
74impl PlatformVersion {
75 pub fn get<'a>(version: ProtocolVersion) -> Result<&'a Self, PlatformVersionError> {
76 if version > 0 {
77 #[cfg(feature = "mock-versions")]
78 {
79 if version >> TEST_PROTOCOL_VERSION_SHIFT_BYTES > 0 {
80 let test_version = version - (1 << TEST_PROTOCOL_VERSION_SHIFT_BYTES);
81
82 let versions = PLATFORM_TEST_VERSIONS
84 .get_or_init(|| vec![TEST_PLATFORM_V2, TEST_PLATFORM_V3]);
85
86 return versions.get(test_version as usize - 2).ok_or(
87 PlatformVersionError::UnknownVersionError(format!(
88 "no test platform version {test_version}"
89 )),
90 );
91 }
92 }
93 PLATFORM_VERSIONS.get(version as usize - 1).ok_or_else(|| {
94 PlatformVersionError::UnknownVersionError(format!("no platform version {version}"))
95 })
96 } else {
97 Err(PlatformVersionError::UnknownVersionError(format!(
98 "no platform version {version}"
99 )))
100 }
101 }
102
103 pub fn get_optional<'a>(version: ProtocolVersion) -> Option<&'a Self> {
104 if version > 0 {
105 #[cfg(feature = "mock-versions")]
106 {
107 if version >> TEST_PROTOCOL_VERSION_SHIFT_BYTES > 0 {
108 let test_version = version - (1 << TEST_PROTOCOL_VERSION_SHIFT_BYTES);
109
110 let versions = PLATFORM_TEST_VERSIONS
112 .get_or_init(|| vec![TEST_PLATFORM_V2, TEST_PLATFORM_V3]);
113
114 return versions.get(test_version as usize - 2);
115 }
116 }
117 PLATFORM_VERSIONS.get(version as usize - 1)
118 } else {
119 None
120 }
121 }
122
123 pub fn get_version_or_latest<'a>(
124 version: Option<ProtocolVersion>,
125 ) -> Result<&'a Self, PlatformVersionError> {
126 if let Some(version) = version {
127 if version > 0 {
128 #[cfg(feature = "mock-versions")]
129 {
130 if version >> TEST_PROTOCOL_VERSION_SHIFT_BYTES > 0 {
131 let test_version = version - (1 << TEST_PROTOCOL_VERSION_SHIFT_BYTES);
132
133 let versions = PLATFORM_TEST_VERSIONS
135 .get_or_init(|| Vec::from(DEFAULT_PLATFORM_TEST_VERSIONS));
136
137 return versions.get(test_version as usize - 2).ok_or(
138 PlatformVersionError::UnknownVersionError(format!(
139 "no test platform version {test_version}"
140 )),
141 );
142 }
143 }
144 PLATFORM_VERSIONS.get(version as usize - 1).ok_or(
145 PlatformVersionError::UnknownVersionError(format!(
146 "no platform version {version}"
147 )),
148 )
149 } else {
150 Err(PlatformVersionError::UnknownVersionError(format!(
151 "no platform version {version}"
152 )))
153 }
154 } else {
155 Ok(Self::latest())
156 }
157 }
158
159 pub fn first<'a>() -> &'a Self {
160 PLATFORM_VERSIONS
161 .first()
162 .expect("expected to have a platform version")
163 }
164
165 pub fn latest<'a>() -> &'a Self {
166 PLATFORM_VERSIONS
167 .last()
168 .expect("expected to have a platform version")
169 }
170
171 pub fn desired<'a>() -> &'a Self {
172 DESIRED_PLATFORM_VERSION
173 }
174
175 #[cfg(feature = "mock-versions")]
176 pub fn replace_test_versions(versions: Vec<PlatformVersion>) {
178 PLATFORM_TEST_VERSIONS
179 .set(versions)
180 .expect("failed to set test versions")
181 }
182}
183
184#[cfg(test)]
185mod shielded_pool_gating_tests {
186 use super::PlatformVersion;
187
188 #[test]
207 fn shielded_block_processing_methods_inactive_before_v12() {
208 let v11 = PlatformVersion::get(11).expect("protocol version 11 must exist");
209 let block_end = &v11.drive_abci.methods.block_end;
210
211 assert_eq!(
212 block_end.record_shielded_pool_anchor, None,
213 "v11 must NOT record shielded pool anchors: the [52, \"M\"] subtree does not exist before v12"
214 );
215 assert_eq!(
216 block_end.prune_shielded_pool_anchors, None,
217 "v11 must NOT prune shielded pool anchors: the [52, \"M\"] subtree does not exist before v12"
218 );
219 }
220
221 #[test]
222 fn shielded_block_processing_methods_active_at_v12() {
223 let v12 = PlatformVersion::get(12).expect("protocol version 12 must exist");
224 let block_end = &v12.drive_abci.methods.block_end;
225
226 assert_eq!(block_end.record_shielded_pool_anchor, Some(0));
229 assert_eq!(block_end.prune_shielded_pool_anchors, Some(0));
230 }
231}