1use std::{
7 hash::{Hash, Hasher},
8 marker::PhantomData,
9};
10
11use hotshot::traits::{
12 implementations::{CombinedNetworks, Libp2pNetwork, MemoryNetwork, PushCdnNetwork},
13 NodeImplementation,
14};
15use hotshot_types::{
16 constants::TEST_UPGRADE_CONSTANTS,
17 data::{EpochNumber, ViewNumber},
18 signature_key::{BLSPubKey, BuilderKey, SchnorrPubKey},
19 traits::node_implementation::{NodeType, Versions},
20 upgrade_config::UpgradeConstants,
21};
22use serde::{Deserialize, Serialize};
23use vbs::version::StaticVersion;
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 View = ViewNumber;
59 type Epoch = EpochNumber;
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 View = ViewNumber;
91 type Epoch = EpochNumber;
92 type BlockHeader = TestBlockHeader;
93 type BlockPayload = TestBlockPayload;
94 type SignatureKey = BLSPubKey;
95 type Transaction = TestTransaction;
96 type ValidatedState = TestValidatedState;
97 type InstanceState = TestInstanceState;
98 type Membership =
99 StrictMembership<TestTypesRandomizedLeader, RandomizedStakeTable<BLSPubKey, SchnorrPubKey>>;
100 type BuilderSignatureKey = BuilderKey;
101 type StateSignatureKey = SchnorrPubKey;
102}
103
104#[derive(Debug, PartialOrd, Ord, serde::Serialize, serde::Deserialize)]
105pub struct TestTypesEpochCatchupTypes<StakeTable: TestStakeTable<BLSPubKey, SchnorrPubKey>> {
106 _pd: PhantomData<StakeTable>,
107}
108
109impl<StakeTable: TestStakeTable<BLSPubKey, SchnorrPubKey>> Default
110 for TestTypesEpochCatchupTypes<StakeTable>
111{
112 fn default() -> Self {
113 Self { _pd: PhantomData }
114 }
115}
116
117impl<StakeTable: TestStakeTable<BLSPubKey, SchnorrPubKey>> Hash
118 for TestTypesEpochCatchupTypes<StakeTable>
119{
120 fn hash<H: Hasher>(&self, state: &mut H) {
121 self._pd.hash(state);
122 }
123}
124
125impl<StakeTable: TestStakeTable<BLSPubKey, SchnorrPubKey>> PartialEq
126 for TestTypesEpochCatchupTypes<StakeTable>
127{
128 fn eq(&self, _other: &Self) -> bool {
129 true
130 }
131}
132
133impl<StakeTable: TestStakeTable<BLSPubKey, SchnorrPubKey>> Eq
134 for TestTypesEpochCatchupTypes<StakeTable>
135{
136}
137
138impl<StakeTable: TestStakeTable<BLSPubKey, SchnorrPubKey>> Copy
139 for TestTypesEpochCatchupTypes<StakeTable>
140{
141}
142
143impl<StakeTable: TestStakeTable<BLSPubKey, SchnorrPubKey>> Clone
144 for TestTypesEpochCatchupTypes<StakeTable>
145{
146 fn clone(&self) -> Self {
147 *self
148 }
149}
150
151impl<StakeTable: TestStakeTable<BLSPubKey, SchnorrPubKey> + 'static> NodeType
152 for TestTypesEpochCatchupTypes<StakeTable>
153{
154 const UPGRADE_CONSTANTS: UpgradeConstants = TEST_UPGRADE_CONSTANTS;
155
156 type View = ViewNumber;
157 type Epoch = EpochNumber;
158 type BlockHeader = TestBlockHeader;
159 type BlockPayload = TestBlockPayload;
160 type SignatureKey = BLSPubKey;
161 type Transaction = TestTransaction;
162 type ValidatedState = TestValidatedState;
163 type InstanceState = TestInstanceState;
164 type Membership = StrictMembership<TestTypesEpochCatchupTypes<StakeTable>, StakeTable>;
165 type BuilderSignatureKey = BuilderKey;
166 type StateSignatureKey = SchnorrPubKey;
167}
168
169#[derive(
170 Copy,
171 Clone,
172 Debug,
173 Default,
174 Hash,
175 PartialEq,
176 Eq,
177 PartialOrd,
178 Ord,
179 serde::Serialize,
180 serde::Deserialize,
181)]
182pub struct TestTypesRandomizedCommitteeMembers<
185 QuorumConfig: QuorumFilterConfig,
186 DaConfig: QuorumFilterConfig,
187> {
188 _pd: PhantomData<QuorumConfig>,
189 _dd: PhantomData<DaConfig>,
190}
191
192impl<QuorumConfig: QuorumFilterConfig, DaConfig: QuorumFilterConfig> NodeType
193 for TestTypesRandomizedCommitteeMembers<QuorumConfig, DaConfig>
194{
195 const UPGRADE_CONSTANTS: UpgradeConstants = TEST_UPGRADE_CONSTANTS;
196
197 type View = ViewNumber;
198 type Epoch = EpochNumber;
199 type BlockHeader = TestBlockHeader;
200 type BlockPayload = TestBlockPayload;
201 type SignatureKey = BLSPubKey;
202 type Transaction = TestTransaction;
203 type ValidatedState = TestValidatedState;
204 type InstanceState = TestInstanceState;
205 type Membership = StrictMembership<
206 TestTypesRandomizedCommitteeMembers<QuorumConfig, DaConfig>,
207 RandomizedCommitteeMembers<BLSPubKey, SchnorrPubKey, QuorumConfig, DaConfig>,
208 >;
209 type BuilderSignatureKey = BuilderKey;
210 type StateSignatureKey = SchnorrPubKey;
211}
212
213#[derive(
214 Copy,
215 Clone,
216 Debug,
217 Default,
218 Hash,
219 PartialEq,
220 Eq,
221 PartialOrd,
222 Ord,
223 serde::Serialize,
224 serde::Deserialize,
225)]
226pub struct TestConsecutiveLeaderTypes;
229impl NodeType for TestConsecutiveLeaderTypes {
230 const UPGRADE_CONSTANTS: UpgradeConstants = TEST_UPGRADE_CONSTANTS;
231
232 type View = ViewNumber;
233 type Epoch = EpochNumber;
234 type BlockHeader = TestBlockHeader;
235 type BlockPayload = TestBlockPayload;
236 type SignatureKey = BLSPubKey;
237 type Transaction = TestTransaction;
238 type ValidatedState = TestValidatedState;
239 type InstanceState = TestInstanceState;
240 type Membership = StrictMembership<
241 TestConsecutiveLeaderTypes,
242 StaticStakeTableLeaderForTwoViews<BLSPubKey, SchnorrPubKey>,
243 >;
244 type BuilderSignatureKey = BuilderKey;
245 type StateSignatureKey = SchnorrPubKey;
246}
247
248#[derive(
249 Copy,
250 Clone,
251 Debug,
252 Default,
253 Hash,
254 PartialEq,
255 Eq,
256 PartialOrd,
257 Ord,
258 serde::Serialize,
259 serde::Deserialize,
260)]
261pub struct TestTwoStakeTablesTypes;
264impl NodeType for TestTwoStakeTablesTypes {
265 const UPGRADE_CONSTANTS: UpgradeConstants = TEST_UPGRADE_CONSTANTS;
266
267 type View = ViewNumber;
268 type Epoch = EpochNumber;
269 type BlockHeader = TestBlockHeader;
270 type BlockPayload = TestBlockPayload;
271 type SignatureKey = BLSPubKey;
272 type Transaction = TestTransaction;
273 type ValidatedState = TestValidatedState;
274 type InstanceState = TestInstanceState;
275 type Membership =
276 StrictMembership<TestTwoStakeTablesTypes, TwoStakeTables<BLSPubKey, SchnorrPubKey>>;
277 type BuilderSignatureKey = BuilderKey;
278 type StateSignatureKey = SchnorrPubKey;
279}
280
281#[derive(Clone, Debug, Deserialize, Serialize, Hash, Eq, PartialEq)]
283pub struct PushCdnImpl;
284
285#[derive(Clone, Debug, Deserialize, Serialize, Hash, Eq, PartialEq)]
287pub struct MemoryImpl;
288
289#[derive(Clone, Debug, Deserialize, Serialize, Hash, Eq, PartialEq)]
291pub struct Libp2pImpl;
292
293#[derive(Clone, Debug, Deserialize, Serialize, Hash, Eq, PartialEq)]
295pub struct WebImpl;
296
297#[derive(Clone, Debug, Deserialize, Serialize, Hash, Eq, PartialEq)]
299pub struct CombinedImpl;
300
301impl<TYPES: NodeType> NodeImplementation<TYPES> for PushCdnImpl {
302 type Network = PushCdnNetwork<TYPES::SignatureKey>;
303 type Storage = TestStorage<TYPES>;
304}
305
306impl<TYPES: NodeType> NodeImplementation<TYPES> for MemoryImpl {
307 type Network = MemoryNetwork<TYPES::SignatureKey>;
308 type Storage = TestStorage<TYPES>;
309}
310
311impl<TYPES: NodeType> NodeImplementation<TYPES> for CombinedImpl {
312 type Network = CombinedNetworks<TYPES>;
313 type Storage = TestStorage<TYPES>;
314}
315
316impl<TYPES: NodeType> NodeImplementation<TYPES> for Libp2pImpl {
317 type Network = Libp2pNetwork<TYPES>;
318 type Storage = TestStorage<TYPES>;
319}
320
321#[derive(Clone, Debug, Copy)]
322pub struct TestVersions {}
323
324impl Versions for TestVersions {
325 type Base = StaticVersion<0, 1>;
326 type Upgrade = StaticVersion<0, 2>;
327 const UPGRADE_HASH: [u8; 32] = [
328 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
329 0, 0,
330 ];
331
332 type Epochs = StaticVersion<0, 4>;
333 type DrbAndHeaderUpgrade = StaticVersion<0, 5>;
334}
335
336#[derive(Clone, Debug, Copy, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
337pub struct EpochsTestVersions {}
338
339impl Versions for EpochsTestVersions {
340 type Base = StaticVersion<0, 3>;
341 type Upgrade = StaticVersion<0, 3>;
342 const UPGRADE_HASH: [u8; 32] = [
343 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
344 0, 0,
345 ];
346
347 type Epochs = StaticVersion<0, 3>;
348 type DrbAndHeaderUpgrade = StaticVersion<0, 5>;
349}
350
351#[derive(Clone, Debug, Copy)]
352pub struct EpochUpgradeTestVersions {}
353
354impl Versions for EpochUpgradeTestVersions {
355 type Base = StaticVersion<0, 3>;
356 type Upgrade = StaticVersion<0, 4>;
357 const UPGRADE_HASH: [u8; 32] = [
358 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
359 0, 0,
360 ];
361
362 type Epochs = StaticVersion<0, 4>;
363 type DrbAndHeaderUpgrade = StaticVersion<0, 5>;
364}
365
366#[derive(Clone, Debug, Copy)]
367pub struct DaCommitteeTestVersions {}
368
369impl Versions for DaCommitteeTestVersions {
370 type Base = StaticVersion<0, 4>;
371 type Upgrade = StaticVersion<0, 4>;
372 const UPGRADE_HASH: [u8; 32] = [
373 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
374 0, 0,
375 ];
376
377 type Epochs = StaticVersion<0, 1>;
378 type DrbAndHeaderUpgrade = StaticVersion<0, 1>;
379}
380
381#[cfg(test)]
382mod tests {
383 use committable::{Commitment, Committable};
384 use hotshot_types::{
385 impl_has_epoch,
386 message::UpgradeLock,
387 simple_vote::{HasEpoch, VersionedVoteData},
388 traits::node_implementation::ConsensusTime,
389 utils::{genesis_epoch_from_version, option_epoch_from_block_number},
390 };
391 use serde::{Deserialize, Serialize};
392
393 use crate::node_types::{EpochsTestVersions, NodeType, TestTypes, TestVersions};
394 #[derive(Serialize, Deserialize, Clone, Copy, Debug, PartialEq, Hash, Eq)]
395 struct TestData<TYPES: NodeType> {
397 data: u64,
398 epoch: Option<TYPES::Epoch>,
399 }
400
401 impl<TYPES: NodeType> Committable for TestData<TYPES> {
402 fn commit(&self) -> Commitment<Self> {
403 committable::RawCommitmentBuilder::new("Test data")
404 .u64(self.data)
405 .finalize()
406 }
407 }
408
409 impl_has_epoch!(TestData<TYPES>);
410
411 #[tokio::test(flavor = "multi_thread")]
412 async fn test_versioned_commitment_includes_view() {
414 let upgrade_lock = UpgradeLock::new();
415
416 let data = TestData {
417 data: 10,
418 epoch: None,
419 };
420
421 let view_0 = <TestTypes as NodeType>::View::new(0);
422 let view_1 = <TestTypes as NodeType>::View::new(1);
423
424 let versioned_data_0 =
425 VersionedVoteData::<TestTypes, TestData<TestTypes>, TestVersions>::new(
426 data,
427 view_0,
428 &upgrade_lock,
429 )
430 .await
431 .unwrap();
432 let versioned_data_1 =
433 VersionedVoteData::<TestTypes, TestData<TestTypes>, TestVersions>::new(
434 data,
435 view_1,
436 &upgrade_lock,
437 )
438 .await
439 .unwrap();
440
441 let versioned_data_commitment_0: [u8; 32] = versioned_data_0.commit().into();
442 let versioned_data_commitment_1: [u8; 32] = versioned_data_1.commit().into();
443
444 assert!(
445 versioned_data_commitment_0 != versioned_data_commitment_1,
446 "left: {versioned_data_commitment_0:?}, right: {versioned_data_commitment_1:?}"
447 );
448 }
449
450 #[test]
451 fn test_option_epoch_from_block_number() {
452 let epoch = option_epoch_from_block_number::<TestTypes>(true, 1, 10);
454 assert_eq!(Some(<TestTypes as NodeType>::Epoch::new(1)), epoch);
455
456 let epoch = option_epoch_from_block_number::<TestTypes>(true, 1, 10);
457 assert_eq!(Some(<TestTypes as NodeType>::Epoch::new(1)), epoch);
458
459 let epoch = option_epoch_from_block_number::<TestTypes>(true, 10, 10);
460 assert_eq!(Some(<TestTypes as NodeType>::Epoch::new(1)), epoch);
461
462 let epoch = option_epoch_from_block_number::<TestTypes>(true, 11, 10);
463 assert_eq!(Some(<TestTypes as NodeType>::Epoch::new(2)), epoch);
464
465 let epoch = option_epoch_from_block_number::<TestTypes>(true, 20, 10);
466 assert_eq!(Some(<TestTypes as NodeType>::Epoch::new(2)), epoch);
467
468 let epoch = option_epoch_from_block_number::<TestTypes>(true, 21, 10);
469 assert_eq!(Some(<TestTypes as NodeType>::Epoch::new(3)), epoch);
470
471 let epoch = option_epoch_from_block_number::<TestTypes>(true, 21, 0);
472 assert_eq!(None, epoch);
473
474 let epoch = option_epoch_from_block_number::<TestTypes>(false, 21, 10);
475 assert_eq!(None, epoch);
476
477 let epoch = option_epoch_from_block_number::<TestTypes>(false, 21, 0);
478 assert_eq!(None, epoch);
479 }
480
481 #[test]
482 fn test_genesis_epoch_from_version() {
483 let epoch = genesis_epoch_from_version::<TestVersions, TestTypes>();
484 assert_eq!(None, epoch);
485
486 let epoch = genesis_epoch_from_version::<EpochsTestVersions, TestTypes>();
487 assert_eq!(Some(<TestTypes as NodeType>::Epoch::new(1)), epoch);
488 }
489}