linera_core/client/chain_client/
state.rs1use std::{collections::BTreeSet, sync::Arc};
6
7use linera_base::data_types::Blob;
8use linera_chain::data_types::ProposedBlock;
9use tokio::sync::Mutex;
10
11use super::super::PendingProposal;
12use crate::data_types::ChainInfo;
13
14pub struct State {
17 pending_proposal: Option<PendingProposal>,
21
22 client_mutex: Arc<Mutex<()>>,
25}
26
27impl State {
28 pub fn new(pending_proposal: Option<PendingProposal>) -> State {
29 State {
30 pending_proposal,
31 client_mutex: Arc::default(),
32 }
33 }
34
35 pub(crate) fn clone_for_update_unchecked(&self) -> State {
38 State {
39 pending_proposal: self.pending_proposal.clone(),
40 client_mutex: Arc::clone(&self.client_mutex),
41 }
42 }
43
44 pub fn pending_proposal(&self) -> &Option<PendingProposal> {
45 &self.pending_proposal
46 }
47
48 pub(super) fn set_pending_proposal(&mut self, block: ProposedBlock, blobs: Vec<Blob>) {
49 if self
50 .pending_proposal
51 .as_ref()
52 .is_some_and(|pending| pending.block.height >= block.height)
53 {
54 tracing::error!(
55 "Not setting pending block at {}, because we already have a pending proposal.",
56 block.height
57 );
58 return;
59 }
60 assert_eq!(
61 block.published_blob_ids(),
62 BTreeSet::from_iter(blobs.iter().map(Blob::id))
63 );
64 self.pending_proposal = Some(PendingProposal { block, blobs });
65 }
66
67 pub(crate) fn update_from_info(&mut self, info: &ChainInfo) {
68 if let Some(pending) = &self.pending_proposal {
69 if pending.block.height < info.next_block_height {
70 tracing::debug!(
71 "Clearing pending proposal: a block was committed at height {}",
72 pending.block.height
73 );
74 self.clear_pending_proposal();
75 }
76 }
77 }
78
79 pub(super) fn clear_pending_proposal(&mut self) {
80 self.pending_proposal = None;
81 }
82
83 pub(super) fn client_mutex(&self) -> Arc<Mutex<()>> {
84 self.client_mutex.clone()
85 }
86}