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