diff --git a/linera-chain/src/manager.rs b/linera-chain/src/manager.rs index 11491e87c15d..a76f2eb0562a 100644 --- a/linera-chain/src/manager.rs +++ b/linera-chain/src/manager.rs @@ -112,9 +112,13 @@ pub struct ChainManager { /// Highest-round authenticated block that we have received and checked. If there are multiple /// proposals in the same round, this contains only the first one. pub proposed: Option, + /// These are blobs belonging to proposed blocks that have not been confirmed yet. + pub proposed_pending_blobs: BTreeMap, /// Latest validated proposal that we have voted to confirm (or would have, if we are not a /// validator). pub locked: Option, + /// These are blobs belonging to validated blocks that have not been confirmed yet. + pub locked_pending_blobs: BTreeMap, /// Latest leader timeout certificate we have received. pub timeout: Option, /// Latest vote we have cast, to validate or confirm. @@ -134,8 +138,6 @@ pub struct ChainManager { pub current_round: Round, /// The owners that take over in fallback mode. pub fallback_owners: BTreeMap, - /// These are blobs belonging to proposed or validated blocks that have not been confirmed yet. - pub pending_blobs: BTreeMap, } doc_scalar!( @@ -196,7 +198,9 @@ impl ChainManager { distribution, fallback_distribution, proposed: None, + proposed_pending_blobs: BTreeMap::new(), locked: None, + locked_pending_blobs: BTreeMap::new(), timeout: None, pending: None, timeout_vote: None, @@ -204,7 +208,6 @@ impl ChainManager { round_timeout, current_round, fallback_owners, - pending_blobs: BTreeMap::new(), }) } @@ -380,6 +383,12 @@ impl ChainManager { ) { // Record the proposed block, so it can be supplied to clients that request it. self.proposed = Some(proposal.clone()); + self.proposed_pending_blobs = proposal + .blobs + .into_iter() + .map(|blob| (blob.id(), blob)) + .collect(); + self.update_current_round(local_time); let ProposalContent { block, round, .. } = proposal.content; let executed_block = outcome.with(block); @@ -394,14 +403,11 @@ impl ChainManager { let value = HashedCertificateValue::new_validated(executed_block.clone()); if let Some(certificate) = lite_cert.with_value(value) { self.locked = Some(certificate); + self.locked_pending_blobs = self.proposed_pending_blobs.clone(); } } } - for blob in proposal.blobs { - self.pending_blobs.insert(blob.id(), blob); - } - if let Some(key_pair) = key_pair { // If this is a fast block, vote to confirm. Otherwise vote to validate. let value = if round.is_fast() { @@ -432,6 +438,7 @@ impl ChainManager { return; }; self.locked = Some(certificate); + self.locked_pending_blobs = self.proposed_pending_blobs.clone(); self.update_current_round(local_time); if let Some(key_pair) = key_pair { // Vote to confirm. @@ -559,9 +566,13 @@ pub struct ChainManagerInfo { pub ownership: ChainOwnership, /// Latest authenticated block that we have received, if requested. pub requested_proposed: Option>, + /// These are blobs belonging to proposed blocks that have not been confirmed yet. + pub proposed_pending_blobs: BTreeMap, /// Latest validated proposal that we have voted to confirm (or would have, if we are not a /// validator). pub requested_locked: Option>, + /// These are blobs belonging to validated blocks that have not been confirmed yet. + pub locked_pending_blobs: BTreeMap, /// Latest timeout certificate we have seen. pub timeout: Option>, /// Latest vote we cast (either to validate or to confirm a block). @@ -579,8 +590,6 @@ pub struct ChainManagerInfo { pub leader: Option, /// The timestamp when the current round times out. pub round_timeout: Option, - /// These are blobs belonging to proposed or validated blocks that have not been confirmed yet. - pub pending_blobs: BTreeMap, } impl From<&ChainManager> for ChainManagerInfo { @@ -589,7 +598,9 @@ impl From<&ChainManager> for ChainManagerInfo { ChainManagerInfo { ownership: manager.ownership.clone(), requested_proposed: None, + proposed_pending_blobs: BTreeMap::new(), requested_locked: None, + locked_pending_blobs: BTreeMap::new(), timeout: manager.timeout.clone().map(Box::new), pending: manager.pending.as_ref().map(|vote| vote.lite()), timeout_vote: manager.timeout_vote.as_ref().map(Vote::lite), @@ -598,7 +609,6 @@ impl From<&ChainManager> for ChainManagerInfo { current_round, leader: manager.round_leader(current_round).cloned(), round_timeout: manager.round_timeout, - pending_blobs: BTreeMap::new(), } } } @@ -612,7 +622,8 @@ impl ChainManagerInfo { .pending .as_ref() .map(|vote| Box::new(vote.value.clone())); - self.pending_blobs = manager.pending_blobs.clone(); + self.locked_pending_blobs = manager.locked_pending_blobs.clone(); + self.proposed_pending_blobs = manager.proposed_pending_blobs.clone(); } /// Gets the highest validated block. diff --git a/linera-core/src/chain_worker/state/mod.rs b/linera-core/src/chain_worker/state/mod.rs index 9d2bf1e72aea..20bea4c5aca3 100644 --- a/linera-core/src/chain_worker/state/mod.rs +++ b/linera-core/src/chain_worker/state/mod.rs @@ -305,12 +305,12 @@ where } /// Returns an error if the block requires a blob we don't have. - /// Looks for the blob in: chain manager's pending blobs and storage. + /// Looks for the blob in: chain manager's proposed pending blobs and storage. async fn check_no_missing_blobs( &self, required_blob_ids: &HashSet, ) -> Result<(), WorkerError> { - let pending_blobs = &self.chain.manager.get().pending_blobs; + let pending_blobs = &self.chain.manager.get().proposed_pending_blobs; let missing_blob_ids = required_blob_ids .iter() .filter(|blob_id| !pending_blobs.contains_key(blob_id)) @@ -348,9 +348,9 @@ where } /// Returns the blobs requested by their `blob_ids` that are either in the chain manager's - /// pending blobs or in storage. + /// locked pending blobs or in storage. async fn get_blobs(&self, blob_ids: &HashSet) -> Result, WorkerError> { - let pending_blobs = &self.chain.manager.get().pending_blobs; + let pending_blobs = &self.chain.manager.get().locked_pending_blobs; let mut found_blobs = Vec::new(); let mut missing_blob_ids = Vec::new(); diff --git a/linera-core/src/client/chain_client_state.rs b/linera-core/src/client/chain_client_state.rs index a8116a0c520d..def6641bb908 100644 --- a/linera-core/src/client/chain_client_state.rs +++ b/linera-core/src/client/chain_client_state.rs @@ -33,15 +33,15 @@ pub struct ChainClientState { /// /// This is always at the same height as `next_block_height`. pending_block: Option, + /// This contains blobs belonging to our `pending_block` that may not even have + /// been processed by (i.e. been proposed to) our own local chain manager yet. + pending_blobs: BTreeMap, /// Known key pairs from present and past identities. known_key_pairs: BTreeMap, /// For each validator, up to which index we have synchronized their /// [`ChainStateView::received_log`]. received_certificate_trackers: HashMap, - /// This contains blobs belonging to our `pending_block` that may not even have - /// been processed by (i.e. been proposed to) our own local chain manager yet. - pending_blobs: BTreeMap, /// A mutex that is held whilst we are performing operations that should not be /// attempted by multiple clients at the same time. diff --git a/linera-core/src/client/mod.rs b/linera-core/src/client/mod.rs index a54421e0a4b5..5e5ad14411b3 100644 --- a/linera-core/src/client/mod.rs +++ b/linera-core/src/client/mod.rs @@ -1802,8 +1802,8 @@ where } } - /// Tries to read blobs from either the pending blobs or the local node's cache, or - /// storage + /// Tries to read blobs from either the proposed pending blobs or the + /// local node's cache, or storage #[instrument(level = "trace")] async fn read_local_blobs( &self, @@ -1822,7 +1822,7 @@ where chain_state_view .manager .get() - .pending_blobs + .proposed_pending_blobs .get(&blob_id) .cloned() }; diff --git a/linera-core/src/local_node.rs b/linera-core/src/local_node.rs index 44df6828f0ee..118c04d3329d 100644 --- a/linera-core/src/local_node.rs +++ b/linera-core/src/local_node.rs @@ -250,7 +250,7 @@ where .await? .manager .get() - .pending_blobs + .locked_pending_blobs .clone(); let mut found_blobs = Vec::new(); for blob_id in missing_blob_ids { diff --git a/linera-core/src/remote_node.rs b/linera-core/src/remote_node.rs index 922ac9526328..4bf7f63f4b19 100644 --- a/linera-core/src/remote_node.rs +++ b/linera-core/src/remote_node.rs @@ -198,7 +198,7 @@ impl RemoteNode { let mut found_blobs = if let Some(info) = info { let new_found_blobs = missing_blobs .iter() - .filter_map(|blob_id| info.manager.pending_blobs.get(blob_id)) + .filter_map(|blob_id| info.manager.locked_pending_blobs.get(blob_id)) .map(|blob| (blob.id(), blob.clone())) .collect::>(); missing_blobs.retain(|blob_id| !new_found_blobs.contains_key(blob_id)); diff --git a/linera-rpc/tests/snapshots/format__format.yaml.snap b/linera-rpc/tests/snapshots/format__format.yaml.snap index 032ee89e0e7b..6d096b431f78 100644 --- a/linera-rpc/tests/snapshots/format__format.yaml.snap +++ b/linera-rpc/tests/snapshots/format__format.yaml.snap @@ -264,9 +264,21 @@ ChainManagerInfo: - requested_proposed: OPTION: TYPENAME: BlockProposal + - proposed_pending_blobs: + MAP: + KEY: + TYPENAME: BlobId + VALUE: + TYPENAME: BlobContent - requested_locked: OPTION: TYPENAME: Certificate + - locked_pending_blobs: + MAP: + KEY: + TYPENAME: BlobId + VALUE: + TYPENAME: BlobContent - timeout: OPTION: TYPENAME: Certificate @@ -290,12 +302,6 @@ ChainManagerInfo: - round_timeout: OPTION: TYPENAME: Timestamp - - pending_blobs: - MAP: - KEY: - TYPENAME: BlobId - VALUE: - TYPENAME: BlobContent ChainOwnership: STRUCT: - super_owners: