Skip to content

Commit

Permalink
fix(core): Allow waking the same message between waits (#3475)
Browse files Browse the repository at this point in the history
Co-authored-by: Arsenii Lyashenko <[email protected]>
Co-authored-by: Dmitry Novikov <[email protected]>
  • Loading branch information
3 people authored Feb 27, 2024
1 parent d87efe7 commit cf483b5
Show file tree
Hide file tree
Showing 21 changed files with 575 additions and 28 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion common/src/storage/complex/messenger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ pub trait Messenger {
///
/// Present to clarify compiler behavior over associated types.
type QueuedDispatch;
/// Stored values type for `Self::DispatchStash`.
///
/// Present to clarify compiler behavior over associated types.
type DelayedDispatch;
/// First key of the waitlist storage.
///
/// Present to clarify compiler behavior over associated types.
Expand Down Expand Up @@ -167,7 +171,7 @@ pub trait Messenger {

type DispatchStash: MapStorage<
Key = Self::DispatchStashKey,
Value = (Self::QueuedDispatch, Interval<Self::BlockNumber>),
Value = (Self::DelayedDispatch, Interval<Self::BlockNumber>),
>;

/// Resets all related to messenger storages.
Expand Down
5 changes: 5 additions & 0 deletions core-processor/src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ pub struct DispatchResult {
pub page_update: BTreeMap<GearPage, PageBuf>,
/// New allocations set for program if it has been changed.
pub allocations: BTreeSet<WasmPage>,
/// Whether this execution sent out a reply.
pub reply_sent: bool,
}

impl DispatchResult {
Expand Down Expand Up @@ -133,6 +135,9 @@ impl DispatchResult {
system_reservation_context,
page_update: Default::default(),
allocations: Default::default(),
// This function is only used to generate a dispatch result if nothing is executed,
// therefore reply_sent will always be false
reply_sent: false,
}
}
}
Expand Down
1 change: 1 addition & 0 deletions core-processor/src/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,7 @@ where
system_reservation_context: info.system_reservation_context,
page_update,
allocations: info.allocations,
reply_sent: info.reply_sent,
})
}

Expand Down
3 changes: 3 additions & 0 deletions core-processor/src/ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ pub struct ExtInfo {
pub reply_deposits: Vec<(MessageId, u64)>,
pub program_candidates_data: BTreeMap<CodeId, Vec<(MessageId, ProgramId)>>,
pub context_store: ContextStore,
pub reply_sent: bool,
}

/// Trait to which ext must have to work in processor wasm executor.
Expand Down Expand Up @@ -394,6 +395,7 @@ impl ProcessorExternalities for Ext {
outgoing_dispatches: generated_dispatches,
awakening,
reply_deposits,
reply_sent,
} = outcome.drain();

let system_reservation_context = SystemReservationContext {
Expand All @@ -419,6 +421,7 @@ impl ProcessorExternalities for Ext {
reply_deposits,
context_store,
program_candidates_data,
reply_sent,
};
Ok(info)
}
Expand Down
3 changes: 2 additions & 1 deletion core-processor/src/processing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,7 @@ pub fn process_success(
context_store,
allocations,
reply_deposits,
reply_sent,
..
} = dispatch_result;

Expand Down Expand Up @@ -453,7 +454,7 @@ pub fn process_success(

// Sending auto-generated reply about success execution.
if matches!(kind, SuccessfulDispatchResultKind::Success)
&& !context_store.reply_sent()
&& !reply_sent
&& !dispatch.is_reply()
&& dispatch.kind() != DispatchKind::Signal
{
Expand Down
16 changes: 15 additions & 1 deletion core/src/message/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@

use crate::{
ids::{MessageId, ProgramId},
message::{DispatchKind, GasLimit, Payload, StoredDispatch, StoredMessage, Value},
message::{
DispatchKind, GasLimit, Payload, StoredDelayedDispatch, StoredDispatch, StoredMessage,
Value,
},
};
use core::ops::Deref;
use gear_core_errors::{ReplyCode, SignalCode};
Expand Down Expand Up @@ -279,6 +282,12 @@ impl From<Dispatch> for StoredDispatch {
}
}

impl From<Dispatch> for StoredDelayedDispatch {
fn from(dispatch: Dispatch) -> StoredDelayedDispatch {
StoredDelayedDispatch::new(dispatch.kind, dispatch.message.into())
}
}

impl From<Dispatch> for (DispatchKind, Message) {
fn from(dispatch: Dispatch) -> (DispatchKind, Message) {
(dispatch.kind, dispatch.message)
Expand All @@ -296,6 +305,11 @@ impl Dispatch {
self.into()
}

/// Convert Dispatch into gasless StoredDelayedDispatch.
pub fn into_stored_delayed(self) -> StoredDelayedDispatch {
self.into()
}

/// Decompose Dispatch for it's components: DispatchKind and Message.
pub fn into_parts(self) -> (DispatchKind, Message) {
self.into()
Expand Down
35 changes: 24 additions & 11 deletions core/src/message/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ pub struct ContextOutcomeDrain {
pub awakening: Vec<(MessageId, u32)>,
/// Reply deposits to be provided.
pub reply_deposits: Vec<(MessageId, u64)>,
/// Whether this execution sent out a reply.
pub reply_sent: bool,
}

/// Context outcome.
Expand Down Expand Up @@ -153,6 +155,7 @@ impl ContextOutcome {
/// Destructs outcome after execution and returns provided dispatches and awaken message ids.
pub fn drain(self) -> ContextOutcomeDrain {
let mut dispatches = Vec::new();
let reply_sent = self.reply.is_some();

for (msg, delay, reservation) in self.init.into_iter() {
dispatches.push((msg.into_dispatch(self.program_id), delay, reservation));
Expand All @@ -174,6 +177,7 @@ impl ContextOutcome {
outgoing_dispatches: dispatches,
awakening: self.awakening,
reply_deposits: self.reply_deposits,
reply_sent,
}
}
}
Expand All @@ -184,13 +188,29 @@ pub struct ContextStore {
outgoing: BTreeMap<u32, Option<Payload>>,
reply: Option<Payload>,
initialized: BTreeSet<ProgramId>,
awaken: BTreeSet<MessageId>,
reply_sent: bool,
reservation_nonce: ReservationNonce,
system_reservation: Option<u64>,
}

impl ContextStore {
// TODO: Remove, only used in migrations (#issue 3721)
/// Create a new context store with the provided parameters.
pub fn new(
outgoing: BTreeMap<u32, Option<Payload>>,
reply: Option<Payload>,
initialized: BTreeSet<ProgramId>,
reservation_nonce: ReservationNonce,
system_reservation: Option<u64>,
) -> Self {
Self {
outgoing,
reply,
initialized,
reservation_nonce,
system_reservation,
}
}

/// Returns stored within message context reservation nonce.
///
/// Will be non zero, if any reservations were created during
Expand Down Expand Up @@ -218,11 +238,6 @@ impl ContextStore {
pub fn system_reservation(&self) -> Option<u64> {
self.system_reservation
}

/// Get info about was reply sent.
pub fn reply_sent(&self) -> bool {
self.reply_sent
}
}

/// Context of currently processing incoming message.
Expand Down Expand Up @@ -268,7 +283,7 @@ impl MessageContext {

/// Return bool defining was reply sent within the execution.
pub fn reply_sent(&self) -> bool {
self.store.reply_sent
self.outcome.reply.is_some()
}

/// Send a new program initialization message.
Expand Down Expand Up @@ -436,7 +451,6 @@ impl MessageContext {
let message = ReplyMessage::from_packet(message_id, packet);

self.outcome.reply = Some((message, reservation));
self.store.reply_sent = true;

Ok(message_id)
} else {
Expand Down Expand Up @@ -486,9 +500,8 @@ impl MessageContext {

/// Wake message by it's message id.
pub fn wake(&mut self, waker_id: MessageId, delay: u32) -> Result<(), Error> {
if self.store.awaken.insert(waker_id) {
if !self.outcome.awakening.iter().any(|v| v.0 == waker_id) {
self.outcome.awakening.push((waker_id, delay));

Ok(())
} else {
Err(Error::DuplicateWaking)
Expand Down
2 changes: 1 addition & 1 deletion core/src/message/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ pub use incoming::{IncomingDispatch, IncomingMessage};
pub use init::{InitMessage, InitPacket};
pub use reply::{ReplyMessage, ReplyPacket};
pub use signal::SignalMessage;
pub use stored::{StoredDispatch, StoredMessage};
pub use stored::{StoredDelayedDispatch, StoredDispatch, StoredMessage};
pub use user::{UserMessage, UserStoredMessage};

use super::buffer::LimitedVec;
Expand Down
55 changes: 55 additions & 0 deletions core/src/message/stored.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,3 +198,58 @@ impl Deref for StoredDispatch {
self.message()
}
}

impl From<StoredDelayedDispatch> for StoredDispatch {
fn from(dispatch: StoredDelayedDispatch) -> Self {
StoredDispatch::new(dispatch.kind, dispatch.message, None)
}
}

/// Stored message with entry point.
///
/// We could use just [`StoredDispatch`]
/// but delayed messages always don't have [`ContextStore`]
/// so we designate this fact via new type.
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Decode, Encode, TypeInfo)]
pub struct StoredDelayedDispatch {
/// Entry point.
kind: DispatchKind,
/// Stored message.
message: StoredMessage,
}

impl From<StoredDelayedDispatch> for (DispatchKind, StoredMessage) {
fn from(dispatch: StoredDelayedDispatch) -> (DispatchKind, StoredMessage) {
(dispatch.kind, dispatch.message)
}
}

impl StoredDelayedDispatch {
/// Create new StoredDelayedDispatch.
pub fn new(kind: DispatchKind, message: StoredMessage) -> Self {
Self { kind, message }
}

/// Decompose StoredDelayedDispatch for it's components: DispatchKind, StoredMessage.
pub fn into_parts(self) -> (DispatchKind, StoredMessage) {
self.into()
}

/// Entry point for the message.
pub fn kind(&self) -> DispatchKind {
self.kind
}

/// Dispatch message reference.
pub fn message(&self) -> &StoredMessage {
&self.message
}
}

impl Deref for StoredDelayedDispatch {
type Target = StoredMessage;

fn deref(&self) -> &Self::Target {
self.message()
}
}
9 changes: 7 additions & 2 deletions gsdk/src/metadata/generated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -796,8 +796,6 @@ pub mod runtime_types {
>,
>,
pub initialized: ::std::vec::Vec<runtime_types::gear_core::ids::ProgramId>,
pub awaken: ::std::vec::Vec<runtime_types::gear_core::ids::MessageId>,
pub reply_sent: ::core::primitive::bool,
pub reservation_nonce:
runtime_types::gear_core::reservation::ReservationNonce,
pub system_reservation: ::core::option::Option<::core::primitive::u64>,
Expand All @@ -808,6 +806,13 @@ pub mod runtime_types {
#[derive(
Debug, crate::gp::Decode, crate::gp::DecodeAsType, crate::gp::Encode,
)]
pub struct StoredDelayedDispatch {
pub kind: runtime_types::gear_core::message::DispatchKind,
pub message: runtime_types::gear_core::message::stored::StoredMessage,
}
#[derive(
Debug, crate::gp::Decode, crate::gp::DecodeAsType, crate::gp::Encode,
)]
pub struct StoredDispatch {
pub kind: runtime_types::gear_core::message::DispatchKind,
pub message: runtime_types::gear_core::message::stored::StoredMessage,
Expand Down
7 changes: 5 additions & 2 deletions pallets/gear-debug/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ pub mod pallet {
use gear_core::{
ids::ProgramId,
memory::PageBuf,
message::{StoredDispatch, StoredMessage},
message::{StoredDelayedDispatch, StoredDispatch, StoredMessage},
pages::{GearPage, PageU32Size, WasmPage},
};
use primitive_types::H256;
Expand All @@ -62,7 +62,10 @@ pub mod pallet {
/// Storage with codes for programs.
type CodeStorage: CodeStorage;

type Messenger: Messenger<QueuedDispatch = StoredDispatch>;
type Messenger: Messenger<
QueuedDispatch = StoredDispatch,
DelayedDispatch = StoredDelayedDispatch,
>;

type ProgramStorage: ProgramStorage
+ IterableMap<(ProgramId, common::Program<BlockNumberFor<Self>>)>;
Expand Down
1 change: 1 addition & 0 deletions pallets/gear-messenger/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ pallet-authorship = { workspace = true, features = ["std"] }
pallet-timestamp = { workspace = true, features = ["std"] }
env_logger.workspace = true
common = { workspace = true, features = ["std"] }
rand.workspace = true

[features]
default = ['std']
Expand Down
11 changes: 7 additions & 4 deletions pallets/gear-messenger/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,8 @@
#![doc(html_logo_url = "https://docs.gear.rs/logo.svg")]
#![doc(html_favicon_url = "https://gear-tech.io/favicons/favicon.ico")]

pub mod migrations;

// Runtime mock for running tests.
#[cfg(test)]
mod mock;
Expand All @@ -161,12 +163,12 @@ pub mod pallet {
use frame_system::pallet_prelude::BlockNumberFor;
use gear_core::{
ids::{MessageId, ProgramId},
message::{StoredDispatch, UserStoredMessage},
message::{StoredDelayedDispatch, StoredDispatch, UserStoredMessage},
};
use sp_std::{convert::TryInto, marker::PhantomData};

/// The current storage version.
pub(crate) const MESSENGER_STORAGE_VERSION: StorageVersion = StorageVersion::new(2);
pub(crate) const MESSENGER_STORAGE_VERSION: StorageVersion = StorageVersion::new(3);

// Gear Messenger Pallet's `Config`.
#[pallet::config]
Expand Down Expand Up @@ -413,14 +415,14 @@ pub mod pallet {
// Private storage for dispatch stash elements.
#[pallet::storage]
pub type DispatchStash<T: Config> =
StorageMap<_, Identity, MessageId, (StoredDispatch, Interval<BlockNumberFor<T>>)>;
StorageMap<_, Identity, MessageId, (StoredDelayedDispatch, Interval<BlockNumberFor<T>>)>;

// Public wrap of the dispatch stash elements.
common::wrap_storage_map!(
storage: DispatchStash,
name: DispatchStashWrap,
key: MessageId,
value: (StoredDispatch, Interval<BlockNumberFor<T>>)
value: (StoredDelayedDispatch, Interval<BlockNumberFor<T>>)
);

// ----
Expand Down Expand Up @@ -591,6 +593,7 @@ pub mod pallet {
type MailboxSecondKey = MessageId;
type MailboxedMessage = UserStoredMessage;
type QueuedDispatch = StoredDispatch;
type DelayedDispatch = StoredDelayedDispatch;
type WaitlistFirstKey = ProgramId;
type WaitlistSecondKey = MessageId;
type WaitlistedMessage = StoredDispatch;
Expand Down
Loading

0 comments on commit cf483b5

Please sign in to comment.