Skip to content

Commit

Permalink
feat: expose the read-only mode via the message context
Browse files Browse the repository at this point in the history
  • Loading branch information
Stebalien committed Nov 28, 2022
1 parent e58a6fc commit 6463bc3
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 1 deletion.
6 changes: 6 additions & 0 deletions fvm/src/kernel/default.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use fvm_shared::econ::TokenAmount;
use fvm_shared::error::ErrorNumber;
use fvm_shared::piece::{zero_piece_commitment, PaddedPieceSize};
use fvm_shared::sector::SectorInfo;
use fvm_shared::sys::out::vm::ContextFlags;
use fvm_shared::{commcid, ActorID};
use lazy_static::lazy_static;
use multihash::MultihashDigest;
Expand Down Expand Up @@ -322,6 +323,11 @@ where
.or_fatal()
.context("invalid gas premium")?,
gas_limit: self.call_manager.gas_tracker().gas_limit().round_down() as u64,
flags: if self.call_manager.state_tree().is_read_only() {
ContextFlags::READ_ONLY
} else {
ContextFlags::empty()
},
})
}
}
Expand Down
10 changes: 10 additions & 0 deletions sdk/src/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,16 @@ use crate::sys;
/// BlockID representing nil parameters or return data.
pub const NO_DATA_BLOCK_ID: u32 = 0;

/// Returns true if the invocation context is read-only. In read-only mode:
///
/// - State-tree updates `sself::set_root` are forbidden.
/// - Actor creation is forbidden.
/// - Value transfers are forbidden.
/// - Events are discarded.
pub fn read_only() -> bool {
super::message::MESSAGE_CONTEXT.flags.read_only()
}

/// Abort execution; exit code must be non zero.
pub fn abort(code: u32, message: Option<&str>) -> ! {
if code == 0 {
Expand Down
21 changes: 21 additions & 0 deletions shared/src/sys/out.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,28 @@ pub mod crypto {
}

pub mod vm {
use bitflags::bitflags;

use crate::sys::TokenAmount;
use crate::{ActorID, MethodNum};

bitflags! {
/// Invocation flags pertaining to the currently executing actor.
#[derive(Default)]
#[repr(transparent)]
pub struct ContextFlags: u64 {
/// Invocation is in "read-only" mode. Any balance transfers, sends that would create
/// actors, and calls to `sself::set_root` and `sself::self_destruct` will be rejected.
const READ_ONLY = 0b00000001;
}
}

impl ContextFlags {
pub fn read_only(self) -> bool {
self.intersects(Self::READ_ONLY)
}
}

#[derive(Debug, Copy, Clone)]
#[repr(packed, C)]
pub struct MessageContext {
Expand All @@ -77,6 +96,8 @@ pub mod vm {
pub gas_premium: TokenAmount,
/// The current gas limit
pub gas_limit: u64,
/// Flags pertaining to the currently executing actor's invocation context.
pub flags: ContextFlags,
}
}

Expand Down
8 changes: 7 additions & 1 deletion testing/integration/tests/fil-readonly-actor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ fn invoke_method(blk: u32, method: u64) -> u32 {
let account = Address::new_secp256k1(&[0u8; SECP_PUB_LEN]).unwrap();
match method {
2 => {
assert!(!sdk::vm::read_only());
// Can't create actors when read-only.
let resp = sdk::send::send_read_only(&account, METHOD_SEND, RawBytes::default());
assert_eq!(resp, Err(ErrorNumber::ReadOnly));
Expand Down Expand Up @@ -51,6 +52,7 @@ fn invoke_method(blk: u32, method: u64) -> u32 {
}
3 => {
// should now be in read-only mode.
assert!(sdk::vm::read_only());

// Sending value fails.
let resp = sdk::send::send(&account, 0, Default::default(), TokenAmount::from_atto(1));
Expand Down Expand Up @@ -122,12 +124,16 @@ fn invoke_method(blk: u32, method: u64) -> u32 {
assert_eq!(err, ActorDeleteError::ReadOnly);
}
4 => {
assert!(sdk::vm::read_only());
// read params and return value entirely in read-only mode.
let input = sdk::ipld::get_block(blk, None).unwrap();
assert_eq!(input, b"input");
return sdk::ipld::put_block(0x55, b"output").unwrap();
}
5 => sdk::vm::abort(42, None),
5 => {
assert!(sdk::vm::read_only());
sdk::vm::abort(42, None)
}
_ => panic!("unexpected method"),
}
0
Expand Down

0 comments on commit 6463bc3

Please sign in to comment.