From 00a86272b8127c14fdddb570c2e97253eb508de7 Mon Sep 17 00:00:00 2001 From: Andreas Fackler Date: Thu, 15 Aug 2024 14:43:56 +0200 Subject: [PATCH] ChainStateView::execute_block can now activate a chain. --- linera-chain/src/chain.rs | 59 +++++++++++++------ linera-chain/src/data_types.rs | 13 +--- .../chain_worker/state/temporary_changes.rs | 2 - 3 files changed, 43 insertions(+), 31 deletions(-) diff --git a/linera-chain/src/chain.rs b/linera-chain/src/chain.rs index 8122db41bc2..6fb695c043c 100644 --- a/linera-chain/src/chain.rs +++ b/linera-chain/src/chain.rs @@ -678,7 +678,7 @@ where } /// Executes a block: first the incoming messages, then the main operation. - /// * Modifies the state of inboxes, outboxes, and channels, if needed. + /// * Modifies the state of outboxes and channels, if needed. /// * As usual, in case of errors, `self` may not be consistent any more and should be thrown /// away. /// * Returns the list of messages caused by the block being executed. @@ -693,6 +693,47 @@ where let chain_id = self.chain_id(); assert_eq!(block.chain_id, chain_id); + // The first incoming message of any child chain must be `OpenChain`. A root chain must + // already be initialized + if block.height == BlockHeight::ZERO + && self + .execution_state + .system + .description + .get() + .map_or(true, |description| description.is_child()) + { + let Some(in_bundle) = block + .incoming_bundles + .first() + .filter(|in_bundle| in_bundle.action == MessageAction::Accept) + else { + return Err(ChainError::InactiveChain(chain_id)); + }; + let Some(posted_message) = + in_bundle.bundle.messages.first().filter(|pm| { + matches!(pm.message, Message::System(SystemMessage::OpenChain(_))) + }) + else { + return Err(ChainError::InactiveChain(chain_id)); + }; + + if !self.is_active() { + let message_id = MessageId { + chain_id: in_bundle.origin.sender, + height: in_bundle.bundle.height, + index: posted_message.index, + }; + self.execute_init_message( + message_id, + &posted_message.message, + block.timestamp, + local_time, + ) + .await?; + } + } + ensure!( *self.execution_state.system.timestamp.get() <= block.timestamp, ChainError::InvalidBlockTimestamp @@ -713,22 +754,6 @@ where ChainError::ClosedChain ); } - - // The first incoming message of any child chain must be `OpenChain`. A root chain must - // already be initialized - if block.height == BlockHeight::ZERO - && self - .execution_state - .system - .description - .get() - .map_or(true, |description| description.is_child()) - { - ensure!( - block.starts_with_open_chain(), - ChainError::InactiveChain(self.chain_id()) - ); - } let app_permissions = self.execution_state.system.application_permissions.get(); let mut mandatory = HashSet::::from_iter( app_permissions.mandatory_applications.iter().cloned(), diff --git a/linera-chain/src/data_types.rs b/linera-chain/src/data_types.rs index c5c941aca6d..bfc3a5cefb7 100644 --- a/linera-chain/src/data_types.rs +++ b/linera-chain/src/data_types.rs @@ -16,7 +16,7 @@ use linera_base::{ }; use linera_execution::{ committee::{Committee, Epoch, ValidatorName}, - BytecodeLocation, Message, MessageKind, Operation, SystemMessage, SystemOperation, + BytecodeLocation, Message, MessageKind, Operation, SystemOperation, }; use serde::{de::Deserializer, Deserialize, Serialize}; @@ -96,17 +96,6 @@ impl Block { .all(|message| message.action == MessageAction::Reject) } - /// Returns whether `OpenChain` is the first message in this block. - pub fn starts_with_open_chain(&self) -> bool { - let Some(posted_message) = self.incoming_messages().next() else { - return false; - }; - matches!( - posted_message.message, - Message::System(SystemMessage::OpenChain(_)) - ) - } - /// Returns an iterator over all incoming [`PostedMessage`]s in this block. pub fn incoming_messages(&self) -> impl Iterator { self.incoming_bundles diff --git a/linera-core/src/chain_worker/state/temporary_changes.rs b/linera-core/src/chain_worker/state/temporary_changes.rs index 7c920983548..f34a4aee544 100644 --- a/linera-core/src/chain_worker/state/temporary_changes.rs +++ b/linera-core/src/chain_worker/state/temporary_changes.rs @@ -139,8 +139,6 @@ where &mut self, block: Block, ) -> Result<(ExecutedBlock, ChainInfoResponse), WorkerError> { - self.0.ensure_is_active()?; - let local_time = self.0.storage.clock().current_time(); let signer = block.authenticated_signer;