1use std::{
7 hash::{Hash, Hasher},
8 marker::PhantomData,
9};
10
11use hotshot::traits::{
12 implementations::{Cliquenet, 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 CliquenetImpl;
296
297#[derive(Clone, Debug, Deserialize, Serialize, Hash, Eq, PartialEq)]
299pub struct WebImpl;
300
301#[derive(Clone, Debug, Deserialize, Serialize, Hash, Eq, PartialEq)]
303pub struct CombinedImpl;
304
305impl<TYPES: NodeType> NodeImplementation<TYPES> for PushCdnImpl {
306 type Network = PushCdnNetwork<TYPES::SignatureKey>;
307 type Storage = TestStorage<TYPES>;
308}
309
310impl<TYPES: NodeType> NodeImplementation<TYPES> for MemoryImpl {
311 type Network = MemoryNetwork<TYPES::SignatureKey>;
312 type Storage = TestStorage<TYPES>;
313}
314
315impl<TYPES: NodeType> NodeImplementation<TYPES> for CombinedImpl {
316 type Network = CombinedNetworks<TYPES>;
317 type Storage = TestStorage<TYPES>;
318}
319
320impl<TYPES: NodeType> NodeImplementation<TYPES> for Libp2pImpl {
321 type Network = Libp2pNetwork<TYPES>;
322 type Storage = TestStorage<TYPES>;
323}
324
325impl<TYPES: NodeType> NodeImplementation<TYPES> for CliquenetImpl {
326 type Network = Cliquenet<TYPES>;
327 type Storage = TestStorage<TYPES>;
328}
329
330#[derive(Clone, Debug, Copy)]
331pub struct TestVersions {}
332
333impl Versions for TestVersions {
334 type Base = StaticVersion<0, 1>;
335 type Upgrade = StaticVersion<0, 2>;
336 const UPGRADE_HASH: [u8; 32] = [
337 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,
338 0, 0,
339 ];
340
341 type Epochs = StaticVersion<0, 4>;
342 type DrbAndHeaderUpgrade = StaticVersion<0, 5>;
343 type Vid2Upgrade = StaticVersion<0, 6>;
344}
345
346#[derive(Clone, Debug, Copy, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
347pub struct EpochsTestVersions {}
348
349impl Versions for EpochsTestVersions {
350 type Base = StaticVersion<0, 3>;
351 type Upgrade = StaticVersion<0, 3>;
352 const UPGRADE_HASH: [u8; 32] = [
353 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,
354 0, 0,
355 ];
356
357 type Epochs = StaticVersion<0, 3>;
358 type DrbAndHeaderUpgrade = StaticVersion<0, 5>;
359 type Vid2Upgrade = StaticVersion<0, 6>;
360}
361
362#[derive(Clone, Debug, Copy)]
363pub struct EpochUpgradeTestVersions {}
364
365impl Versions for EpochUpgradeTestVersions {
366 type Base = StaticVersion<0, 3>;
367 type Upgrade = StaticVersion<0, 4>;
368 const UPGRADE_HASH: [u8; 32] = [
369 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,
370 0, 0,
371 ];
372
373 type Epochs = StaticVersion<0, 4>;
374 type DrbAndHeaderUpgrade = StaticVersion<0, 5>;
375 type Vid2Upgrade = StaticVersion<0, 6>;
376}
377
378#[derive(Clone, Debug, Copy)]
379pub struct DaCommitteeTestVersions {}
380
381impl Versions for DaCommitteeTestVersions {
382 type Base = StaticVersion<0, 4>;
383 type Upgrade = StaticVersion<0, 4>;
384 const UPGRADE_HASH: [u8; 32] = [
385 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,
386 0, 0,
387 ];
388
389 type Epochs = StaticVersion<0, 1>;
390 type DrbAndHeaderUpgrade = StaticVersion<0, 1>;
391 type Vid2Upgrade = StaticVersion<0, 6>;
393}
394
395#[derive(Clone, Debug, Copy, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
396pub struct Vid2TestVersions {}
397
398impl Versions for Vid2TestVersions {
399 type Base = StaticVersion<0, 6>;
400 type Upgrade = StaticVersion<0, 6>;
401 const UPGRADE_HASH: [u8; 32] = [
402 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,
403 0, 0,
404 ];
405
406 type Epochs = StaticVersion<0, 3>;
407 type DrbAndHeaderUpgrade = StaticVersion<0, 5>;
408 type Vid2Upgrade = StaticVersion<0, 6>;
409}
410
411#[derive(Clone, Debug, Copy, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
412pub struct Vid2UpgradeTestVersions {}
413
414impl Versions for Vid2UpgradeTestVersions {
415 type Base = StaticVersion<0, 5>;
416 type Upgrade = StaticVersion<0, 6>;
417 const UPGRADE_HASH: [u8; 32] = [
418 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,
419 0, 0,
420 ];
421
422 type Epochs = StaticVersion<0, 3>;
423 type DrbAndHeaderUpgrade = StaticVersion<0, 5>;
424 type Vid2Upgrade = StaticVersion<0, 6>;
425}
426
427#[cfg(test)]
428mod tests {
429 use committable::{Commitment, Committable};
430 use hotshot_types::{
431 impl_has_epoch,
432 message::UpgradeLock,
433 simple_vote::{HasEpoch, VersionedVoteData},
434 traits::node_implementation::ConsensusTime,
435 utils::{genesis_epoch_from_version, option_epoch_from_block_number},
436 };
437 use serde::{Deserialize, Serialize};
438
439 use crate::node_types::{EpochsTestVersions, NodeType, TestTypes, TestVersions};
440 #[derive(Serialize, Deserialize, Clone, Copy, Debug, PartialEq, Hash, Eq)]
441 struct TestData<TYPES: NodeType> {
443 data: u64,
444 epoch: Option<TYPES::Epoch>,
445 }
446
447 impl<TYPES: NodeType> Committable for TestData<TYPES> {
448 fn commit(&self) -> Commitment<Self> {
449 committable::RawCommitmentBuilder::new("Test data")
450 .u64(self.data)
451 .finalize()
452 }
453 }
454
455 impl_has_epoch!(TestData<TYPES>);
456
457 #[tokio::test(flavor = "multi_thread")]
458 async fn test_versioned_commitment_includes_view() {
460 let upgrade_lock = UpgradeLock::new();
461
462 let data = TestData {
463 data: 10,
464 epoch: None,
465 };
466
467 let view_0 = <TestTypes as NodeType>::View::new(0);
468 let view_1 = <TestTypes as NodeType>::View::new(1);
469
470 let versioned_data_0 =
471 VersionedVoteData::<TestTypes, TestData<TestTypes>, TestVersions>::new(
472 data,
473 view_0,
474 &upgrade_lock,
475 )
476 .await
477 .unwrap();
478 let versioned_data_1 =
479 VersionedVoteData::<TestTypes, TestData<TestTypes>, TestVersions>::new(
480 data,
481 view_1,
482 &upgrade_lock,
483 )
484 .await
485 .unwrap();
486
487 let versioned_data_commitment_0: [u8; 32] = versioned_data_0.commit().into();
488 let versioned_data_commitment_1: [u8; 32] = versioned_data_1.commit().into();
489
490 assert!(
491 versioned_data_commitment_0 != versioned_data_commitment_1,
492 "left: {versioned_data_commitment_0:?}, right: {versioned_data_commitment_1:?}"
493 );
494 }
495
496 #[test]
497 fn test_option_epoch_from_block_number() {
498 let epoch = option_epoch_from_block_number::<TestTypes>(true, 1, 10);
500 assert_eq!(Some(<TestTypes as NodeType>::Epoch::new(1)), epoch);
501
502 let epoch = option_epoch_from_block_number::<TestTypes>(true, 1, 10);
503 assert_eq!(Some(<TestTypes as NodeType>::Epoch::new(1)), epoch);
504
505 let epoch = option_epoch_from_block_number::<TestTypes>(true, 10, 10);
506 assert_eq!(Some(<TestTypes as NodeType>::Epoch::new(1)), epoch);
507
508 let epoch = option_epoch_from_block_number::<TestTypes>(true, 11, 10);
509 assert_eq!(Some(<TestTypes as NodeType>::Epoch::new(2)), epoch);
510
511 let epoch = option_epoch_from_block_number::<TestTypes>(true, 20, 10);
512 assert_eq!(Some(<TestTypes as NodeType>::Epoch::new(2)), epoch);
513
514 let epoch = option_epoch_from_block_number::<TestTypes>(true, 21, 10);
515 assert_eq!(Some(<TestTypes as NodeType>::Epoch::new(3)), epoch);
516
517 let epoch = option_epoch_from_block_number::<TestTypes>(true, 21, 0);
518 assert_eq!(None, epoch);
519
520 let epoch = option_epoch_from_block_number::<TestTypes>(false, 21, 10);
521 assert_eq!(None, epoch);
522
523 let epoch = option_epoch_from_block_number::<TestTypes>(false, 21, 0);
524 assert_eq!(None, epoch);
525 }
526
527 #[test]
528 fn test_genesis_epoch_from_version() {
529 let epoch = genesis_epoch_from_version::<TestVersions, TestTypes>();
530 assert_eq!(None, epoch);
531
532 let epoch = genesis_epoch_from_version::<EpochsTestVersions, TestTypes>();
533 assert_eq!(Some(<TestTypes as NodeType>::Epoch::new(1)), epoch);
534 }
535}