1use crate::{
18 consensus::{ConsensusClientId, StateMachineClient, StateMachineHeight},
19 error::Error,
20 events::Event,
21 host::IsmpHost,
22 messaging::Message,
23};
24
25use crate::{consensus::ConsensusStateId, module::DispatchResult};
26use alloc::{boxed::Box, vec::Vec};
27pub use consensus::create_client;
28use sp_weights::Weight;
29
30mod consensus;
31mod request;
32mod response;
33mod timeout;
34
35pub struct ConsensusClientCreatedResult {
37 pub consensus_client_id: ConsensusClientId,
39 pub consensus_state_id: ConsensusStateId,
41}
42
43#[derive(Debug)]
45pub enum MessageResult {
46 ConsensusMessage(Vec<Event>),
48 FrozenClient(ConsensusStateId),
50 Request {
52 events: Vec<DispatchResult>,
54 weight: Weight,
56 },
57 Response {
59 events: Vec<DispatchResult>,
61 weight: Weight,
63 },
64 Timeout {
66 events: Vec<DispatchResult>,
68 weight: Weight,
70 },
71}
72
73impl MessageResult {
74 pub fn weight(&self) -> Weight {
76 match self {
77 MessageResult::Request { weight, .. } => *weight,
78 MessageResult::Response { weight, .. } => *weight,
79 MessageResult::Timeout { weight, .. } => *weight,
80 MessageResult::ConsensusMessage(_) | MessageResult::FrozenClient(_) => Weight::zero(),
81 }
82 }
83}
84
85pub fn handle_incoming_message<H>(
87 host: &H,
88 message: Message,
89) -> Result<MessageResult, anyhow::Error>
90where
91 H: IsmpHost,
92{
93 match message {
94 Message::Consensus(consensus_message) => consensus::update_client(host, consensus_message),
95 Message::FraudProof(fraud_proof) => consensus::freeze_client(host, fraud_proof),
96 Message::Request(req) => request::handle(host, req),
97 Message::Response(resp) => response::handle(host, resp),
98 Message::Timeout(timeout) => timeout::handle(host, timeout),
99 }
100}
101
102pub fn verify_delay_passed<H>(host: &H, proof_height: &StateMachineHeight) -> Result<bool, Error>
105where
106 H: IsmpHost,
107{
108 let update_time = host.state_machine_update_time(*proof_height)?;
109 let delay_period = host
110 .challenge_period(proof_height.id)
111 .ok_or(Error::ChallengePeriodNotConfigured { state_machine: proof_height.id })?;
112 let current_timestamp = host.timestamp();
113 Ok(delay_period.as_secs() == 0 || current_timestamp.saturating_sub(update_time) > delay_period)
114}
115
116pub fn validate_state_machine<H>(
122 host: &H,
123 proof_height: StateMachineHeight,
124) -> Result<Box<dyn StateMachineClient>, Error>
125where
126 H: IsmpHost,
127{
128 let consensus_client_id = host.consensus_client_id(proof_height.id.consensus_state_id).ok_or(
130 Error::ConsensusStateIdNotRecognized {
131 consensus_state_id: proof_height.id.consensus_state_id,
132 },
133 )?;
134 let consensus_client = host.consensus_client(consensus_client_id)?;
135 host.is_consensus_client_frozen(proof_height.id.consensus_state_id)?;
137
138 if !verify_delay_passed(host, &proof_height)? {
140 return Err(Error::ChallengePeriodNotElapsed {
141 state_machine_id: proof_height.id,
142 current_time: host.timestamp(),
143 update_time: host.state_machine_update_time(proof_height)?,
144 });
145 }
146
147 consensus_client.state_machine(proof_height.id.state_id)
148}