hotshot/tasks/
task_state.rs

1// Copyright (c) 2021-2024 Espresso Systems (espressosys.com)
2// This file is part of the HotShot repository.
3
4// You should have received a copy of the MIT License
5// along with the HotShot repository. If not, see <https://mit-license.org/>.
6
7use std::{
8    collections::BTreeMap,
9    sync::{atomic::AtomicBool, Arc},
10    time::Instant,
11};
12
13use async_trait::async_trait;
14use chrono::Utc;
15use hotshot_task_impls::{
16    builder::BuilderClient, consensus::ConsensusTaskState, da::DaTaskState,
17    quorum_proposal::QuorumProposalTaskState, quorum_proposal_recv::QuorumProposalRecvTaskState,
18    quorum_vote::QuorumVoteTaskState, request::NetworkRequestState, rewind::RewindTaskState,
19    stats::StatsTaskState, transactions::TransactionTaskState, upgrade::UpgradeTaskState,
20    vid::VidTaskState, view_sync::ViewSyncTaskState,
21};
22use hotshot_types::{
23    consensus::OuterConsensus,
24    traits::{
25        consensus_api::ConsensusApi,
26        node_implementation::{ConsensusTime, NodeImplementation, NodeType},
27    },
28};
29use tokio::spawn;
30
31use crate::{types::SystemContextHandle, Versions};
32
33/// Trait for creating task states.
34#[async_trait]
35pub trait CreateTaskState<TYPES, I, V>
36where
37    TYPES: NodeType,
38    I: NodeImplementation<TYPES>,
39    V: Versions,
40{
41    /// Function to create the task state from a given `SystemContextHandle`.
42    async fn create_from(handle: &SystemContextHandle<TYPES, I, V>) -> Self;
43}
44
45#[async_trait]
46impl<TYPES: NodeType, I: NodeImplementation<TYPES>, V: Versions> CreateTaskState<TYPES, I, V>
47    for NetworkRequestState<TYPES, I>
48{
49    async fn create_from(handle: &SystemContextHandle<TYPES, I, V>) -> Self {
50        Self {
51            network: Arc::clone(&handle.hotshot.network),
52            consensus: OuterConsensus::new(handle.hotshot.consensus()),
53            view: handle.cur_view().await,
54            delay: handle.hotshot.config.data_request_delay,
55            membership_coordinator: handle.hotshot.membership_coordinator.clone(),
56            public_key: handle.public_key().clone(),
57            private_key: handle.private_key().clone(),
58            id: handle.hotshot.id,
59            shutdown_flag: Arc::new(AtomicBool::new(false)),
60            spawned_tasks: BTreeMap::new(),
61            epoch_height: handle.epoch_height,
62        }
63    }
64}
65
66#[async_trait]
67impl<TYPES: NodeType, I: NodeImplementation<TYPES>, V: Versions> CreateTaskState<TYPES, I, V>
68    for UpgradeTaskState<TYPES, V>
69{
70    async fn create_from(handle: &SystemContextHandle<TYPES, I, V>) -> Self {
71        #[cfg(not(feature = "example-upgrade"))]
72        return Self {
73            output_event_stream: handle.hotshot.external_event_stream.0.clone(),
74            cur_view: handle.cur_view().await,
75            cur_epoch: handle.cur_epoch().await,
76            membership_coordinator: handle.hotshot.membership_coordinator.clone(),
77            vote_collectors: BTreeMap::default(),
78            public_key: handle.public_key().clone(),
79            private_key: handle.private_key().clone(),
80            id: handle.hotshot.id,
81            start_proposing_view: handle.hotshot.config.start_proposing_view,
82            stop_proposing_view: handle.hotshot.config.stop_proposing_view,
83            start_voting_view: handle.hotshot.config.start_voting_view,
84            stop_voting_view: handle.hotshot.config.stop_voting_view,
85            start_proposing_time: handle.hotshot.config.start_proposing_time,
86            stop_proposing_time: handle.hotshot.config.stop_proposing_time,
87            start_voting_time: handle.hotshot.config.start_voting_time,
88            stop_voting_time: handle.hotshot.config.stop_voting_time,
89            epoch_start_block: handle.hotshot.config.epoch_start_block,
90            upgrade_lock: handle.hotshot.upgrade_lock.clone(),
91            epoch_height: handle.epoch_height,
92            consensus: OuterConsensus::new(handle.hotshot.consensus()),
93        };
94
95        #[cfg(feature = "example-upgrade")]
96        return Self {
97            output_event_stream: handle.hotshot.external_event_stream.0.clone(),
98            cur_view: handle.cur_view().await,
99            cur_epoch: handle.cur_epoch().await,
100            membership: Arc::clone(&handle.hotshot.memberships),
101            network: Arc::clone(&handle.hotshot.network),
102            vote_collector: None.into(),
103            public_key: handle.public_key().clone(),
104            private_key: handle.private_key().clone(),
105            id: handle.hotshot.id,
106            start_proposing_view: 5,
107            stop_proposing_view: 10,
108            start_voting_view: 0,
109            stop_voting_view: 20,
110            start_proposing_time: 0,
111            stop_proposing_time: u64::MAX,
112            start_voting_time: 0,
113            stop_voting_time: u64::MAX,
114            upgrade_lock: handle.hotshot.upgrade_lock.clone(),
115        };
116    }
117}
118
119#[async_trait]
120impl<TYPES: NodeType, I: NodeImplementation<TYPES>, V: Versions> CreateTaskState<TYPES, I, V>
121    for VidTaskState<TYPES, I, V>
122{
123    async fn create_from(handle: &SystemContextHandle<TYPES, I, V>) -> Self {
124        Self {
125            consensus: OuterConsensus::new(handle.hotshot.consensus()),
126            cur_view: handle.cur_view().await,
127            cur_epoch: handle.cur_epoch().await,
128            network: Arc::clone(&handle.hotshot.network),
129            membership_coordinator: handle.hotshot.membership_coordinator.clone(),
130            public_key: handle.public_key().clone(),
131            private_key: handle.private_key().clone(),
132            id: handle.hotshot.id,
133            upgrade_lock: handle.hotshot.upgrade_lock.clone(),
134            epoch_height: handle.epoch_height,
135        }
136    }
137}
138
139#[async_trait]
140impl<TYPES: NodeType, I: NodeImplementation<TYPES>, V: Versions> CreateTaskState<TYPES, I, V>
141    for DaTaskState<TYPES, I, V>
142{
143    async fn create_from(handle: &SystemContextHandle<TYPES, I, V>) -> Self {
144        Self {
145            consensus: OuterConsensus::new(handle.hotshot.consensus()),
146            output_event_stream: handle.hotshot.external_event_stream.0.clone(),
147            membership_coordinator: handle.hotshot.membership_coordinator.clone(),
148            network: Arc::clone(&handle.hotshot.network),
149            cur_view: handle.cur_view().await,
150            cur_epoch: handle.cur_epoch().await,
151            vote_collectors: BTreeMap::default(),
152            public_key: handle.public_key().clone(),
153            private_key: handle.private_key().clone(),
154            id: handle.hotshot.id,
155            storage: handle.storage.clone(),
156            storage_metrics: handle.storage_metrics(),
157            upgrade_lock: handle.hotshot.upgrade_lock.clone(),
158        }
159    }
160}
161
162#[async_trait]
163impl<TYPES: NodeType, I: NodeImplementation<TYPES>, V: Versions> CreateTaskState<TYPES, I, V>
164    for ViewSyncTaskState<TYPES, V>
165{
166    async fn create_from(handle: &SystemContextHandle<TYPES, I, V>) -> Self {
167        let cur_view = handle.cur_view().await;
168
169        Self {
170            cur_view,
171            next_view: cur_view,
172            cur_epoch: handle.cur_epoch().await,
173            membership_coordinator: handle.hotshot.membership_coordinator.clone(),
174            public_key: handle.public_key().clone(),
175            private_key: handle.private_key().clone(),
176            num_timeouts_tracked: 0,
177            replica_task_map: BTreeMap::default().into(),
178            pre_commit_relay_map: BTreeMap::default().into(),
179            commit_relay_map: BTreeMap::default().into(),
180            finalize_relay_map: BTreeMap::default().into(),
181            view_sync_timeout: handle.hotshot.config.view_sync_timeout,
182            id: handle.hotshot.id,
183            last_garbage_collected_view: TYPES::View::new(0),
184            upgrade_lock: handle.hotshot.upgrade_lock.clone(),
185            first_epoch: None,
186            highest_finalized_epoch_view: (None, TYPES::View::new(0)),
187            epoch_height: handle.epoch_height,
188        }
189    }
190}
191
192#[async_trait]
193impl<TYPES: NodeType, I: NodeImplementation<TYPES>, V: Versions> CreateTaskState<TYPES, I, V>
194    for TransactionTaskState<TYPES, V>
195{
196    async fn create_from(handle: &SystemContextHandle<TYPES, I, V>) -> Self {
197        Self {
198            builder_timeout: handle.builder_timeout(),
199            output_event_stream: handle.hotshot.external_event_stream.0.clone(),
200            consensus: OuterConsensus::new(handle.hotshot.consensus()),
201            cur_view: handle.cur_view().await,
202            cur_epoch: handle.cur_epoch().await,
203            membership_coordinator: handle.hotshot.membership_coordinator.clone(),
204            public_key: handle.public_key().clone(),
205            private_key: handle.private_key().clone(),
206            instance_state: handle.hotshot.instance_state(),
207            id: handle.hotshot.id,
208            builder_clients: handle
209                .hotshot
210                .config
211                .builder_urls
212                .iter()
213                .cloned()
214                .map(|url| BuilderClient::new(url, handle.builder_timeout()))
215                .collect(),
216            upgrade_lock: handle.hotshot.upgrade_lock.clone(),
217            epoch_height: handle.epoch_height,
218        }
219    }
220}
221
222#[async_trait]
223impl<TYPES: NodeType, I: NodeImplementation<TYPES>, V: Versions> CreateTaskState<TYPES, I, V>
224    for QuorumVoteTaskState<TYPES, I, V>
225{
226    async fn create_from(handle: &SystemContextHandle<TYPES, I, V>) -> Self {
227        let consensus = handle.hotshot.consensus();
228
229        // Clone the consensus metrics
230        let consensus_metrics = Arc::clone(&consensus.read().await.metrics);
231
232        Self {
233            public_key: handle.public_key().clone(),
234            private_key: handle.private_key().clone(),
235            state_private_key: handle.state_private_key().clone(),
236            consensus: OuterConsensus::new(consensus),
237            instance_state: handle.hotshot.instance_state(),
238            latest_voted_view: handle.cur_view().await,
239            vote_dependencies: BTreeMap::new(),
240            network: Arc::clone(&handle.hotshot.network),
241            membership: handle.hotshot.membership_coordinator.clone(),
242            output_event_stream: handle.hotshot.external_event_stream.0.clone(),
243            id: handle.hotshot.id,
244            storage: handle.storage.clone(),
245            storage_metrics: handle.storage_metrics(),
246            upgrade_lock: handle.hotshot.upgrade_lock.clone(),
247            epoch_height: handle.hotshot.config.epoch_height,
248            consensus_metrics,
249            first_epoch: None,
250            stake_table_capacity: handle.hotshot.config.stake_table_capacity,
251            da_committees: handle.hotshot.config.da_committees.clone(),
252        }
253    }
254}
255
256#[async_trait]
257impl<TYPES: NodeType, I: NodeImplementation<TYPES>, V: Versions> CreateTaskState<TYPES, I, V>
258    for QuorumProposalTaskState<TYPES, I, V>
259{
260    async fn create_from(handle: &SystemContextHandle<TYPES, I, V>) -> Self {
261        let consensus = handle.hotshot.consensus();
262
263        Self {
264            latest_proposed_view: handle.cur_view().await,
265            cur_epoch: handle.cur_epoch().await,
266            proposal_dependencies: BTreeMap::new(),
267            formed_state_cert: BTreeMap::new(),
268            formed_quorum_certificates: BTreeMap::new(),
269            formed_next_epoch_quorum_certificates: BTreeMap::new(),
270            consensus: OuterConsensus::new(consensus),
271            instance_state: handle.hotshot.instance_state(),
272            membership_coordinator: handle.hotshot.membership_coordinator.clone(),
273            public_key: handle.public_key().clone(),
274            private_key: handle.private_key().clone(),
275            storage: handle.storage.clone(),
276            timeout: handle.hotshot.config.next_view_timeout,
277            id: handle.hotshot.id,
278            formed_upgrade_certificate: None,
279            upgrade_lock: handle.hotshot.upgrade_lock.clone(),
280            epoch_height: handle.hotshot.config.epoch_height,
281            first_epoch: None,
282        }
283    }
284}
285
286#[async_trait]
287impl<TYPES: NodeType, I: NodeImplementation<TYPES>, V: Versions> CreateTaskState<TYPES, I, V>
288    for QuorumProposalRecvTaskState<TYPES, I, V>
289{
290    async fn create_from(handle: &SystemContextHandle<TYPES, I, V>) -> Self {
291        let consensus = handle.hotshot.consensus();
292
293        Self {
294            public_key: handle.public_key().clone(),
295            private_key: handle.private_key().clone(),
296            consensus: OuterConsensus::new(consensus),
297            cur_view: handle.cur_view().await,
298            cur_epoch: handle.cur_epoch().await,
299            membership: handle.hotshot.membership_coordinator.clone(),
300            timeout: handle.hotshot.config.next_view_timeout,
301            output_event_stream: handle.hotshot.external_event_stream.0.clone(),
302            storage: handle.storage.clone(),
303            spawned_tasks: BTreeMap::new(),
304            id: handle.hotshot.id,
305            upgrade_lock: handle.hotshot.upgrade_lock.clone(),
306            epoch_height: handle.hotshot.config.epoch_height,
307            first_epoch: None,
308        }
309    }
310}
311
312#[async_trait]
313impl<TYPES: NodeType, I: NodeImplementation<TYPES>, V: Versions> CreateTaskState<TYPES, I, V>
314    for ConsensusTaskState<TYPES, I, V>
315{
316    async fn create_from(handle: &SystemContextHandle<TYPES, I, V>) -> Self {
317        let consensus = handle.hotshot.consensus();
318
319        Self {
320            public_key: handle.public_key().clone(),
321            private_key: handle.private_key().clone(),
322            instance_state: handle.hotshot.instance_state(),
323            network: Arc::clone(&handle.hotshot.network),
324            membership_coordinator: handle.hotshot.membership_coordinator.clone(),
325            vote_collectors: BTreeMap::default(),
326            epoch_root_vote_collectors: BTreeMap::default(),
327            next_epoch_vote_collectors: BTreeMap::default(),
328            timeout_vote_collectors: BTreeMap::default(),
329            cur_view: handle.cur_view().await,
330            cur_view_time: Utc::now().timestamp(),
331            cur_epoch: handle.cur_epoch().await,
332            output_event_stream: handle.hotshot.external_event_stream.0.clone(),
333            timeout_task: spawn(async {}),
334            timeout: handle.hotshot.config.next_view_timeout,
335            consensus: OuterConsensus::new(consensus),
336            storage: handle.storage.clone(),
337            id: handle.hotshot.id,
338            upgrade_lock: handle.hotshot.upgrade_lock.clone(),
339            epoch_height: handle.hotshot.config.epoch_height,
340            view_start_time: Instant::now(),
341            first_epoch: None,
342        }
343    }
344}
345
346#[async_trait]
347impl<TYPES: NodeType, I: NodeImplementation<TYPES>, V: Versions> CreateTaskState<TYPES, I, V>
348    for StatsTaskState<TYPES>
349{
350    async fn create_from(handle: &SystemContextHandle<TYPES, I, V>) -> Self {
351        StatsTaskState::<TYPES>::new(
352            handle.cur_view().await,
353            handle.cur_epoch().await,
354            handle.public_key().clone(),
355            OuterConsensus::new(handle.hotshot.consensus()),
356            handle.hotshot.membership_coordinator.clone(),
357        )
358    }
359}
360
361#[async_trait]
362impl<TYPES: NodeType, I: NodeImplementation<TYPES>, V: Versions> CreateTaskState<TYPES, I, V>
363    for RewindTaskState<TYPES>
364{
365    async fn create_from(handle: &SystemContextHandle<TYPES, I, V>) -> Self {
366        Self {
367            events: Vec::new(),
368            id: handle.hotshot.id,
369        }
370    }
371}