1use std::{
7 hash::{Hash, Hasher},
8 marker::PhantomData,
9};
10
11use hotshot::traits::{
12 NodeImplementation,
13 implementations::{CombinedNetworks, Libp2pNetwork, MemoryNetwork, PushCdnNetwork},
14};
15use hotshot_types::{
16 constants::TEST_UPGRADE_CONSTANTS,
17 signature_key::{BLSPubKey, BuilderKey, SchnorrPubKey},
18 traits::node_implementation::NodeType,
19 upgrade_config::UpgradeConstants,
20};
21use serde::{Deserialize, Serialize};
22use vbs::version::StaticVersion;
23use versions::{Upgrade, version};
24
25pub use crate::membership::helpers::{RandomOverlapQuorumFilterConfig, StableQuorumFilterConfig};
26use crate::{
27 block_types::{TestBlockHeader, TestBlockPayload, TestTransaction},
28 membership::{
29 helpers::QuorumFilterConfig, randomized_committee::RandomizedStakeTable,
30 randomized_committee_members::RandomizedCommitteeMembers, stake_table::TestStakeTable,
31 static_committee::StaticStakeTable,
32 static_committee_leader_two_views::StaticStakeTableLeaderForTwoViews,
33 strict_membership::StrictMembership, two_static_committees::TwoStakeTables,
34 },
35 state_types::{TestInstanceState, TestValidatedState},
36 storage_types::TestStorage,
37};
38
39#[derive(
40 Copy,
41 Clone,
42 Debug,
43 Default,
44 Hash,
45 PartialEq,
46 Eq,
47 PartialOrd,
48 Ord,
49 serde::Serialize,
50 serde::Deserialize,
51)]
52pub struct TestTypes;
55impl NodeType for TestTypes {
56 const UPGRADE_CONSTANTS: UpgradeConstants = TEST_UPGRADE_CONSTANTS;
57
58 type BlockHeader = TestBlockHeader;
59 type BlockPayload = TestBlockPayload;
60 type SignatureKey = BLSPubKey;
61 type Transaction = TestTransaction;
62 type ValidatedState = TestValidatedState;
63 type InstanceState = TestInstanceState;
64 type Membership = StrictMembership<TestTypes, StaticStakeTable<BLSPubKey, SchnorrPubKey>>;
65 type BuilderSignatureKey = BuilderKey;
66 type StateSignatureKey = SchnorrPubKey;
67}
68
69#[derive(
70 Copy,
71 Clone,
72 Debug,
73 Default,
74 Hash,
75 PartialEq,
76 Eq,
77 PartialOrd,
78 Ord,
79 serde::Serialize,
80 serde::Deserialize,
81)]
82pub struct TestTypesRandomizedLeader;
85impl NodeType for TestTypesRandomizedLeader {
86 const UPGRADE_CONSTANTS: UpgradeConstants = TEST_UPGRADE_CONSTANTS;
87
88 type BlockHeader = TestBlockHeader;
89 type BlockPayload = TestBlockPayload;
90 type SignatureKey = BLSPubKey;
91 type Transaction = TestTransaction;
92 type ValidatedState = TestValidatedState;
93 type InstanceState = TestInstanceState;
94 type Membership =
95 StrictMembership<TestTypesRandomizedLeader, RandomizedStakeTable<BLSPubKey, SchnorrPubKey>>;
96 type BuilderSignatureKey = BuilderKey;
97 type StateSignatureKey = SchnorrPubKey;
98}
99
100#[derive(Debug, PartialOrd, Ord, serde::Serialize, serde::Deserialize)]
101pub struct TestTypesEpochCatchupTypes<StakeTable: TestStakeTable<BLSPubKey, SchnorrPubKey>> {
102 _pd: PhantomData<StakeTable>,
103}
104
105impl<StakeTable: TestStakeTable<BLSPubKey, SchnorrPubKey>> Default
106 for TestTypesEpochCatchupTypes<StakeTable>
107{
108 fn default() -> Self {
109 Self { _pd: PhantomData }
110 }
111}
112
113impl<StakeTable: TestStakeTable<BLSPubKey, SchnorrPubKey>> Hash
114 for TestTypesEpochCatchupTypes<StakeTable>
115{
116 fn hash<H: Hasher>(&self, state: &mut H) {
117 self._pd.hash(state);
118 }
119}
120
121impl<StakeTable: TestStakeTable<BLSPubKey, SchnorrPubKey>> PartialEq
122 for TestTypesEpochCatchupTypes<StakeTable>
123{
124 fn eq(&self, _other: &Self) -> bool {
125 true
126 }
127}
128
129impl<StakeTable: TestStakeTable<BLSPubKey, SchnorrPubKey>> Eq
130 for TestTypesEpochCatchupTypes<StakeTable>
131{
132}
133
134impl<StakeTable: TestStakeTable<BLSPubKey, SchnorrPubKey>> Copy
135 for TestTypesEpochCatchupTypes<StakeTable>
136{
137}
138
139impl<StakeTable: TestStakeTable<BLSPubKey, SchnorrPubKey>> Clone
140 for TestTypesEpochCatchupTypes<StakeTable>
141{
142 fn clone(&self) -> Self {
143 *self
144 }
145}
146
147impl<StakeTable: TestStakeTable<BLSPubKey, SchnorrPubKey> + 'static> NodeType
148 for TestTypesEpochCatchupTypes<StakeTable>
149{
150 const UPGRADE_CONSTANTS: UpgradeConstants = TEST_UPGRADE_CONSTANTS;
151
152 type BlockHeader = TestBlockHeader;
153 type BlockPayload = TestBlockPayload;
154 type SignatureKey = BLSPubKey;
155 type Transaction = TestTransaction;
156 type ValidatedState = TestValidatedState;
157 type InstanceState = TestInstanceState;
158 type Membership = StrictMembership<TestTypesEpochCatchupTypes<StakeTable>, StakeTable>;
159 type BuilderSignatureKey = BuilderKey;
160 type StateSignatureKey = SchnorrPubKey;
161}
162
163#[derive(
164 Copy,
165 Clone,
166 Debug,
167 Default,
168 Hash,
169 PartialEq,
170 Eq,
171 PartialOrd,
172 Ord,
173 serde::Serialize,
174 serde::Deserialize,
175)]
176pub struct TestTypesRandomizedCommitteeMembers<
179 QuorumConfig: QuorumFilterConfig,
180 DaConfig: QuorumFilterConfig,
181> {
182 _pd: PhantomData<QuorumConfig>,
183 _dd: PhantomData<DaConfig>,
184}
185
186impl<QuorumConfig: QuorumFilterConfig, DaConfig: QuorumFilterConfig> NodeType
187 for TestTypesRandomizedCommitteeMembers<QuorumConfig, DaConfig>
188{
189 const UPGRADE_CONSTANTS: UpgradeConstants = TEST_UPGRADE_CONSTANTS;
190
191 type BlockHeader = TestBlockHeader;
192 type BlockPayload = TestBlockPayload;
193 type SignatureKey = BLSPubKey;
194 type Transaction = TestTransaction;
195 type ValidatedState = TestValidatedState;
196 type InstanceState = TestInstanceState;
197 type Membership = StrictMembership<
198 TestTypesRandomizedCommitteeMembers<QuorumConfig, DaConfig>,
199 RandomizedCommitteeMembers<BLSPubKey, SchnorrPubKey, QuorumConfig, DaConfig>,
200 >;
201 type BuilderSignatureKey = BuilderKey;
202 type StateSignatureKey = SchnorrPubKey;
203}
204
205#[derive(
206 Copy,
207 Clone,
208 Debug,
209 Default,
210 Hash,
211 PartialEq,
212 Eq,
213 PartialOrd,
214 Ord,
215 serde::Serialize,
216 serde::Deserialize,
217)]
218pub struct TestConsecutiveLeaderTypes;
221impl NodeType for TestConsecutiveLeaderTypes {
222 const UPGRADE_CONSTANTS: UpgradeConstants = TEST_UPGRADE_CONSTANTS;
223
224 type BlockHeader = TestBlockHeader;
225 type BlockPayload = TestBlockPayload;
226 type SignatureKey = BLSPubKey;
227 type Transaction = TestTransaction;
228 type ValidatedState = TestValidatedState;
229 type InstanceState = TestInstanceState;
230 type Membership = StrictMembership<
231 TestConsecutiveLeaderTypes,
232 StaticStakeTableLeaderForTwoViews<BLSPubKey, SchnorrPubKey>,
233 >;
234 type BuilderSignatureKey = BuilderKey;
235 type StateSignatureKey = SchnorrPubKey;
236}
237
238#[derive(
239 Copy,
240 Clone,
241 Debug,
242 Default,
243 Hash,
244 PartialEq,
245 Eq,
246 PartialOrd,
247 Ord,
248 serde::Serialize,
249 serde::Deserialize,
250)]
251pub struct TestTwoStakeTablesTypes;
254impl NodeType for TestTwoStakeTablesTypes {
255 const UPGRADE_CONSTANTS: UpgradeConstants = TEST_UPGRADE_CONSTANTS;
256
257 type BlockHeader = TestBlockHeader;
258 type BlockPayload = TestBlockPayload;
259 type SignatureKey = BLSPubKey;
260 type Transaction = TestTransaction;
261 type ValidatedState = TestValidatedState;
262 type InstanceState = TestInstanceState;
263 type Membership =
264 StrictMembership<TestTwoStakeTablesTypes, TwoStakeTables<BLSPubKey, SchnorrPubKey>>;
265 type BuilderSignatureKey = BuilderKey;
266 type StateSignatureKey = SchnorrPubKey;
267}
268
269#[derive(Clone, Debug, Deserialize, Serialize, Hash, Eq, PartialEq)]
271pub struct PushCdnImpl;
272
273#[derive(Clone, Debug, Deserialize, Serialize, Hash, Eq, PartialEq)]
275pub struct MemoryImpl;
276
277#[derive(Clone, Debug, Deserialize, Serialize, Hash, Eq, PartialEq)]
279pub struct Libp2pImpl;
280
281#[derive(Clone, Debug, Deserialize, Serialize, Hash, Eq, PartialEq)]
283pub struct WebImpl;
284
285#[derive(Clone, Debug, Deserialize, Serialize, Hash, Eq, PartialEq)]
287pub struct CombinedImpl;
288
289impl<TYPES: NodeType> NodeImplementation<TYPES> for PushCdnImpl {
290 type Network = PushCdnNetwork<TYPES::SignatureKey>;
291 type Storage = TestStorage<TYPES>;
292}
293
294impl<TYPES: NodeType> NodeImplementation<TYPES> for MemoryImpl {
295 type Network = MemoryNetwork<TYPES::SignatureKey>;
296 type Storage = TestStorage<TYPES>;
297}
298
299impl<TYPES: NodeType> NodeImplementation<TYPES> for CombinedImpl {
300 type Network = CombinedNetworks<TYPES>;
301 type Storage = TestStorage<TYPES>;
302}
303
304impl<TYPES: NodeType> NodeImplementation<TYPES> for Libp2pImpl {
305 type Network = Libp2pNetwork<TYPES>;
306 type Storage = TestStorage<TYPES>;
307}
308
309#[non_exhaustive]
310pub struct TestVersions {
311 pub test: Upgrade,
312 pub epoch: Upgrade,
313 pub da_committee: Upgrade,
314 pub vid2: Upgrade,
315 pub epoch_upgrade: Upgrade,
316 pub vid2_upgrade: Upgrade,
317}
318
319pub const TEST_VERSIONS: TestVersions = TestVersions {
320 epoch: Upgrade::trivial(version(0, 3)),
321 da_committee: Upgrade::trivial(version(0, 4)),
322 vid2: Upgrade::trivial(version(0, 6)),
323 test: Upgrade::new(version(0, 1), version(0, 2)),
324 epoch_upgrade: Upgrade::new(version(0, 3), version(0, 4)),
325 vid2_upgrade: Upgrade::new(version(0, 5), version(0, 6)),
326};
327
328pub type EpochVersion = StaticVersion<0, 3>;
329#[cfg(test)]
333mod tests {
334 use committable::{Commitment, Committable};
335 use hotshot_types::{
336 data::{EpochNumber, ViewNumber},
337 impl_has_epoch,
338 message::UpgradeLock,
339 simple_vote::{HasEpoch, VersionedVoteData},
340 utils::{genesis_epoch_from_version, option_epoch_from_block_number},
341 };
342 use serde::{Deserialize, Serialize};
343 use versions::{EPOCH_VERSION, Upgrade, version};
344
345 use crate::node_types::TestTypes;
346 #[derive(Serialize, Deserialize, Clone, Copy, Debug, PartialEq, Hash, Eq)]
347 struct TestData {
349 data: u64,
350 epoch: Option<EpochNumber>,
351 }
352
353 impl Committable for TestData {
354 fn commit(&self) -> Commitment<Self> {
355 committable::RawCommitmentBuilder::new("Test data")
356 .u64(self.data)
357 .finalize()
358 }
359 }
360
361 impl_has_epoch!(TestData);
362
363 #[tokio::test(flavor = "multi_thread")]
365 async fn test_versioned_commitment_includes_view() {
366 let upgrade_lock = UpgradeLock::new(Upgrade::new(version(0, 1), version(0, 2)));
367
368 let data = TestData {
369 data: 10,
370 epoch: None,
371 };
372
373 let view_0 = ViewNumber::new(0);
374 let view_1 = ViewNumber::new(1);
375
376 let versioned_data_0 =
377 VersionedVoteData::<TestTypes, TestData>::new(data, view_0, &upgrade_lock).unwrap();
378 let versioned_data_1 =
379 VersionedVoteData::<TestTypes, TestData>::new(data, view_1, &upgrade_lock).unwrap();
380
381 let versioned_data_commitment_0: [u8; 32] = versioned_data_0.commit().into();
382 let versioned_data_commitment_1: [u8; 32] = versioned_data_1.commit().into();
383
384 assert!(
385 versioned_data_commitment_0 != versioned_data_commitment_1,
386 "left: {versioned_data_commitment_0:?}, right: {versioned_data_commitment_1:?}"
387 );
388 }
389
390 #[test]
391 fn test_option_epoch_from_block_number() {
392 let epoch = option_epoch_from_block_number(true, 1, 10);
394 assert_eq!(Some(EpochNumber::new(1)), epoch);
395
396 let epoch = option_epoch_from_block_number(true, 1, 10);
397 assert_eq!(Some(EpochNumber::new(1)), epoch);
398
399 let epoch = option_epoch_from_block_number(true, 10, 10);
400 assert_eq!(Some(EpochNumber::new(1)), epoch);
401
402 let epoch = option_epoch_from_block_number(true, 11, 10);
403 assert_eq!(Some(EpochNumber::new(2)), epoch);
404
405 let epoch = option_epoch_from_block_number(true, 20, 10);
406 assert_eq!(Some(EpochNumber::new(2)), epoch);
407
408 let epoch = option_epoch_from_block_number(true, 21, 10);
409 assert_eq!(Some(EpochNumber::new(3)), epoch);
410
411 let epoch = option_epoch_from_block_number(true, 21, 0);
412 assert_eq!(None, epoch);
413
414 let epoch = option_epoch_from_block_number(false, 21, 10);
415 assert_eq!(None, epoch);
416
417 let epoch = option_epoch_from_block_number(false, 21, 0);
418 assert_eq!(None, epoch);
419 }
420
421 #[test]
422 fn test_genesis_epoch_from_version() {
423 let epoch = genesis_epoch_from_version(version(0, 1));
424 assert_eq!(None, epoch);
425
426 let epoch = genesis_epoch_from_version(EPOCH_VERSION);
427 assert_eq!(Some(EpochNumber::new(1)), epoch);
428 }
429}