Skip to content
This repository has been archived by the owner on Jan 29, 2024. It is now read-only.

Cross execution #75

Merged
merged 6 commits into from
Mar 28, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion gateway/src/checkpoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use num_traits::Zero;
use primitives::{TCid, TLink};
use serde_tuple::{Deserialize_tuple, Serialize_tuple};

use crate::{CrossMsg, CrossMsgs};
use crate::{ensure_message_sorted, CrossMsg, CrossMsgs};

#[derive(PartialEq, Eq, Clone, Debug, Serialize_tuple, Deserialize_tuple)]
pub struct Checkpoint {
Expand Down Expand Up @@ -69,6 +69,13 @@ impl Checkpoint {
self.data.cross_msgs.cross_msgs.take()
}

pub fn ensure_cross_msgs_sorted(&self) -> anyhow::Result<()> {
match self.data.cross_msgs.cross_msgs.as_ref() {
None => Ok(()),
Some(v) => ensure_message_sorted(v),
}
}

/// Get the sum of values in cross messages
pub fn total_value(&self) -> TokenAmount {
match &self.data.cross_msgs.cross_msgs {
Expand Down
15 changes: 2 additions & 13 deletions gateway/src/cron.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::StorableMsg;
use crate::{ensure_message_sorted, StorableMsg};
use anyhow::anyhow;
use cid::multihash::Code;
use cid::multihash::MultihashDigest;
Expand All @@ -13,7 +13,6 @@ use ipc_sdk::ValidatorSet;
use lazy_static::lazy_static;
use num_traits::Zero;
use primitives::{TCid, THamt};
use std::cmp::Ordering;
use std::ops::Mul;

pub type HashOutput = Vec<u8>;
Expand Down Expand Up @@ -75,17 +74,7 @@ impl CronCheckpoint {
///
/// Actor will not perform sorting to save gas. Client should do it, actor just check.
pub fn hash(&self) -> anyhow::Result<HashOutput> {
// check top down msgs
for i in 1..self.top_down_msgs.len() {
match self.top_down_msgs[i - 1]
.nonce
.cmp(&self.top_down_msgs[i].nonce)
{
Ordering::Less => {}
Ordering::Equal => return Err(anyhow!("top down messages not distinct")),
Ordering::Greater => return Err(anyhow!("top down messages not sorted")),
};
}
ensure_message_sorted(&self.top_down_msgs)?;

let mh_code = Code::Blake2b256;
// TODO: to avoid serialization again, maybe we should perform deserialization in the actor
Expand Down
14 changes: 13 additions & 1 deletion gateway/src/cross.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::ApplyMsgParams;
use crate::State;
use crate::SUBNET_ACTOR_REWARD_METHOD;
use crate::{ApplyMsgParams, ExecutableMessage};
use anyhow::anyhow;
use fil_actors_runtime::runtime::Runtime;
use fil_actors_runtime::ActorError;
Expand Down Expand Up @@ -33,12 +33,24 @@ pub struct StorableMsg {
pub nonce: u64,
}

impl ExecutableMessage for StorableMsg {
fn nonce(&self) -> u64 {
self.nonce
}
}

#[derive(PartialEq, Eq, Clone, Debug, Serialize_tuple, Deserialize_tuple)]
pub struct CrossMsg {
pub msg: StorableMsg,
pub wrapped: bool,
}

impl ExecutableMessage for CrossMsg {
fn nonce(&self) -> u64 {
self.msg.nonce()
}
}

#[derive(PartialEq, Eq)]
pub enum IPCMsgType {
BottomUp,
Expand Down
7 changes: 7 additions & 0 deletions gateway/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,13 @@ impl Actor {
// we should update here.
rt.validate_immediate_caller_accept_any()?;

commit.ensure_cross_msgs_sorted().map_err(|_| {
actor_error!(
illegal_argument,
"cross messages not ordered by nonce"
)
})?;

let subnet_addr = rt.message().caller();
let subnet_actor = commit.source().subnet_actor();

Expand Down
20 changes: 20 additions & 0 deletions gateway/src/types.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use anyhow::anyhow;
use cid::multihash::Code;
use cid::{multihash, Cid};
use fil_actors_runtime::{cbor, ActorError, Array};
Expand All @@ -9,6 +10,7 @@ use fvm_shared::econ::TokenAmount;
use ipc_sdk::subnet_id::SubnetID;
use multihash::MultihashDigest;
use primitives::CodeType;
use std::cmp::Ordering;

use crate::checkpoint::{Checkpoint, CrossMsgMeta};
use crate::cross::CrossMsg;
Expand All @@ -25,6 +27,12 @@ pub const SUBNET_ACTOR_REWARD_METHOD: u64 = frc42_dispatch::method_hash!("Reward
pub type CrossMsgMetaArray<'bs, BS> = Array<'bs, CrossMsgMeta, BS>;
pub type CrossMsgArray<'bs, BS> = Array<'bs, CrossMsg, BS>;

/// The executable message trait
pub trait ExecutableMessage {
/// Get the nonce of the message
fn nonce(&self) -> u64;
}

#[derive(Serialize_tuple, Deserialize_tuple)]
pub struct ConstructorParams {
pub network_name: String,
Expand Down Expand Up @@ -100,6 +108,18 @@ impl PostBoxItem {
}
}

pub(crate) fn ensure_message_sorted<E: ExecutableMessage>(messages: &[E]) -> anyhow::Result<()> {
// check top down msgs
for i in 1..messages.len() {
match messages[i - 1].nonce().cmp(&messages[i].nonce()) {
Ordering::Less => {}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cryptoAtwill, I don´t think we should throw an error here. Let's just order them in case they are not ordered and return them. If the checkpoint was committed here it was because all the validators agreed on that, so we can trust the messages (is not the same as for cron checkpoints). Let's discuss if this is not clear.

Ordering::Equal => return Err(anyhow!("top down messages not distinct")),
Ordering::Greater => return Err(anyhow!("top down messages not sorted")),
};
}
Ok(())
}

#[cfg(test)]
mod tests {
use crate::ConstructorParams;
Expand Down