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(BuilderClient::new)
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        }
252    }
253}
254
255#[async_trait]
256impl<TYPES: NodeType, I: NodeImplementation<TYPES>, V: Versions> CreateTaskState<TYPES, I, V>
257    for QuorumProposalTaskState<TYPES, I, V>
258{
259    async fn create_from(handle: &SystemContextHandle<TYPES, I, V>) -> Self {
260        let consensus = handle.hotshot.consensus();
261
262        Self {
263            latest_proposed_view: handle.cur_view().await,
264            cur_epoch: handle.cur_epoch().await,
265            proposal_dependencies: BTreeMap::new(),
266            formed_state_cert: BTreeMap::new(),
267            formed_quorum_certificates: BTreeMap::new(),
268            formed_next_epoch_quorum_certificates: BTreeMap::new(),
269            consensus: OuterConsensus::new(consensus),
270            instance_state: handle.hotshot.instance_state(),
271            membership_coordinator: handle.hotshot.membership_coordinator.clone(),
272            public_key: handle.public_key().clone(),
273            private_key: handle.private_key().clone(),
274            storage: handle.storage.clone(),
275            timeout: handle.hotshot.config.next_view_timeout,
276            id: handle.hotshot.id,
277            formed_upgrade_certificate: None,
278            upgrade_lock: handle.hotshot.upgrade_lock.clone(),
279            epoch_height: handle.hotshot.config.epoch_height,
280            first_epoch: None,
281        }
282    }
283}
284
285#[async_trait]
286impl<TYPES: NodeType, I: NodeImplementation<TYPES>, V: Versions> CreateTaskState<TYPES, I, V>
287    for QuorumProposalRecvTaskState<TYPES, I, V>
288{
289    async fn create_from(handle: &SystemContextHandle<TYPES, I, V>) -> Self {
290        let consensus = handle.hotshot.consensus();
291
292        Self {
293            public_key: handle.public_key().clone(),
294            private_key: handle.private_key().clone(),
295            consensus: OuterConsensus::new(consensus),
296            cur_view: handle.cur_view().await,
297            cur_epoch: handle.cur_epoch().await,
298            membership: handle.hotshot.membership_coordinator.clone(),
299            timeout: handle.hotshot.config.next_view_timeout,
300            output_event_stream: handle.hotshot.external_event_stream.0.clone(),
301            storage: handle.storage.clone(),
302            spawned_tasks: BTreeMap::new(),
303            id: handle.hotshot.id,
304            upgrade_lock: handle.hotshot.upgrade_lock.clone(),
305            epoch_height: handle.hotshot.config.epoch_height,
306            first_epoch: None,
307        }
308    }
309}
310
311#[async_trait]
312impl<TYPES: NodeType, I: NodeImplementation<TYPES>, V: Versions> CreateTaskState<TYPES, I, V>
313    for ConsensusTaskState<TYPES, I, V>
314{
315    async fn create_from(handle: &SystemContextHandle<TYPES, I, V>) -> Self {
316        let consensus = handle.hotshot.consensus();
317
318        Self {
319            public_key: handle.public_key().clone(),
320            private_key: handle.private_key().clone(),
321            instance_state: handle.hotshot.instance_state(),
322            network: Arc::clone(&handle.hotshot.network),
323            membership_coordinator: handle.hotshot.membership_coordinator.clone(),
324            vote_collectors: BTreeMap::default(),
325            epoch_root_vote_collectors: BTreeMap::default(),
326            next_epoch_vote_collectors: BTreeMap::default(),
327            timeout_vote_collectors: BTreeMap::default(),
328            cur_view: handle.cur_view().await,
329            cur_view_time: Utc::now().timestamp(),
330            cur_epoch: handle.cur_epoch().await,
331            output_event_stream: handle.hotshot.external_event_stream.0.clone(),
332            timeout_task: spawn(async {}),
333            timeout: handle.hotshot.config.next_view_timeout,
334            consensus: OuterConsensus::new(consensus),
335            storage: handle.storage.clone(),
336            id: handle.hotshot.id,
337            upgrade_lock: handle.hotshot.upgrade_lock.clone(),
338            epoch_height: handle.hotshot.config.epoch_height,
339            view_start_time: Instant::now(),
340            first_epoch: None,
341        }
342    }
343}
344
345#[async_trait]
346impl<TYPES: NodeType, I: NodeImplementation<TYPES>, V: Versions> CreateTaskState<TYPES, I, V>
347    for StatsTaskState<TYPES>
348{
349    async fn create_from(handle: &SystemContextHandle<TYPES, I, V>) -> Self {
350        StatsTaskState::<TYPES>::new(
351            handle.cur_view().await,
352            handle.cur_epoch().await,
353            handle.public_key().clone(),
354            OuterConsensus::new(handle.hotshot.consensus()),
355            handle.hotshot.membership_coordinator.clone(),
356        )
357    }
358}
359
360#[async_trait]
361impl<TYPES: NodeType, I: NodeImplementation<TYPES>, V: Versions> CreateTaskState<TYPES, I, V>
362    for RewindTaskState<TYPES>
363{
364    async fn create_from(handle: &SystemContextHandle<TYPES, I, V>) -> Self {
365        Self {
366            events: Vec::new(),
367            id: handle.hotshot.id,
368        }
369    }
370}