Skip to main content

fedimint_client_module/sm/
executor.rs

1use std::io::{self, Read, Write};
2use std::sync::Arc;
3use std::time::SystemTime;
4
5use fedimint_core::core::{ModuleInstanceId, OperationId};
6use fedimint_core::db::DatabaseTransaction;
7use fedimint_core::encoding::{
8    Decodable, DecodeError, Encodable, decode_legacy_system_time_from_finite_reader,
9    encode_legacy_system_time, with_decoding_context,
10};
11use fedimint_core::module::registry::ModuleDecoderRegistry;
12use fedimint_core::{apply, async_trait_maybe_send, maybe_add_send_sync};
13
14use super::DynState;
15use crate::{AddStateMachinesResult, DynGlobalClientContext};
16
17pub type ContextGen =
18    Arc<maybe_add_send_sync!(dyn Fn(ModuleInstanceId, OperationId) -> DynGlobalClientContext)>;
19
20/// A state that is able to make progress eventually
21#[derive(Debug)]
22pub struct ActiveStateKey {
23    // TODO: remove redundant operation id from state trait
24    pub operation_id: OperationId,
25    // TODO: state being a key... seems ... risky?
26    pub state: DynState,
27}
28
29impl ActiveStateKey {
30    pub fn from_state(state: DynState) -> ActiveStateKey {
31        ActiveStateKey {
32            operation_id: state.operation_id(),
33            state,
34        }
35    }
36}
37
38impl Encodable for ActiveStateKey {
39    fn consensus_encode<W: Write>(&self, writer: &mut W) -> Result<(), io::Error> {
40        self.operation_id.consensus_encode(writer)?;
41        self.state.consensus_encode(writer)?;
42        Ok(())
43    }
44}
45
46impl Decodable for ActiveStateKey {
47    fn consensus_decode_partial<R: Read>(
48        reader: &mut R,
49        modules: &ModuleDecoderRegistry,
50    ) -> Result<Self, DecodeError> {
51        let operation_id = OperationId::consensus_decode_partial(reader, modules)?;
52        let state = DynState::consensus_decode_partial(reader, modules)?;
53
54        Ok(ActiveStateKey {
55            operation_id,
56            state,
57        })
58    }
59}
60
61#[derive(Debug, Copy, Clone)]
62pub struct ActiveStateMeta {
63    pub created_at: SystemTime,
64}
65
66impl Encodable for ActiveStateMeta {
67    fn consensus_encode<W: Write>(&self, writer: &mut W) -> Result<(), io::Error> {
68        encode_legacy_system_time(&self.created_at, writer)
69    }
70}
71
72impl Decodable for ActiveStateMeta {
73    fn consensus_decode_partial_from_finite_reader<R: Read>(
74        reader: &mut R,
75        modules: &ModuleDecoderRegistry,
76    ) -> Result<Self, DecodeError> {
77        Ok(Self {
78            created_at: with_decoding_context(
79                decode_legacy_system_time_from_finite_reader(reader, modules),
80                "Decoding named block field: ActiveStateMeta{ ... created_at ... }",
81            )?,
82        })
83    }
84}
85
86impl ActiveStateMeta {
87    pub fn into_inactive(self) -> InactiveStateMeta {
88        InactiveStateMeta {
89            created_at: self.created_at,
90            exited_at: fedimint_core::time::now(),
91        }
92    }
93}
94
95impl Default for ActiveStateMeta {
96    fn default() -> Self {
97        Self {
98            created_at: fedimint_core::time::now(),
99        }
100    }
101}
102
103/// A past or final state of a state machine
104#[derive(Debug, Clone)]
105pub struct InactiveStateKey {
106    // TODO: remove redundant operation id from state trait
107    pub operation_id: OperationId,
108    pub state: DynState,
109}
110
111impl InactiveStateKey {
112    pub fn from_state(state: DynState) -> InactiveStateKey {
113        InactiveStateKey {
114            operation_id: state.operation_id(),
115            state,
116        }
117    }
118}
119
120impl Encodable for InactiveStateKey {
121    fn consensus_encode<W: Write>(&self, writer: &mut W) -> Result<(), std::io::Error> {
122        self.operation_id.consensus_encode(writer)?;
123        self.state.consensus_encode(writer)?;
124        Ok(())
125    }
126}
127
128impl Decodable for InactiveStateKey {
129    fn consensus_decode_partial<R: Read>(
130        reader: &mut R,
131        modules: &ModuleDecoderRegistry,
132    ) -> Result<Self, DecodeError> {
133        let operation_id = OperationId::consensus_decode_partial(reader, modules)?;
134        let state = DynState::consensus_decode_partial(reader, modules)?;
135
136        Ok(InactiveStateKey {
137            operation_id,
138            state,
139        })
140    }
141}
142
143#[derive(Debug, Copy, Clone)]
144pub struct InactiveStateMeta {
145    pub created_at: SystemTime,
146    pub exited_at: SystemTime,
147}
148
149impl Encodable for InactiveStateMeta {
150    fn consensus_encode<W: Write>(&self, writer: &mut W) -> Result<(), io::Error> {
151        encode_legacy_system_time(&self.created_at, writer)?;
152        encode_legacy_system_time(&self.exited_at, writer)
153    }
154}
155
156impl Decodable for InactiveStateMeta {
157    fn consensus_decode_partial_from_finite_reader<R: Read>(
158        reader: &mut R,
159        modules: &ModuleDecoderRegistry,
160    ) -> Result<Self, DecodeError> {
161        Ok(Self {
162            created_at: with_decoding_context(
163                decode_legacy_system_time_from_finite_reader(reader, modules),
164                "Decoding named block field: InactiveStateMeta{ ... created_at ... }",
165            )?,
166            exited_at: with_decoding_context(
167                decode_legacy_system_time_from_finite_reader(reader, modules),
168                "Decoding named block field: InactiveStateMeta{ ... exited_at ... }",
169            )?,
170        })
171    }
172}
173
174#[apply(async_trait_maybe_send!)]
175pub trait IExecutor {
176    async fn get_active_states(&self) -> Vec<(DynState, ActiveStateMeta)>;
177
178    async fn add_state_machines_dbtx(
179        &self,
180        dbtx: &mut DatabaseTransaction<'_>,
181        states: Vec<DynState>,
182    ) -> AddStateMachinesResult;
183}