Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(fvm): fix (and prevent) two bugs in out of gas handling. #1830

Merged
merged 1 commit into from
Aug 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
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
28 changes: 12 additions & 16 deletions fvm/src/call_manager/default.rs
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,7 @@ where
None => {
// We charge for creating the actor (storage) but not for address assignment as the
// init actor has already handled that for us.
let _ = self.charge_gas(self.price_list().on_create_actor(false))?;
self.charge_gas(self.price_list().on_create_actor(false))?;
ActorState::new_empty(code_id, delegated_address)
}
};
Expand All @@ -422,8 +422,7 @@ where
return Ok(Some(id));
}
if !self.state_access_tracker.get_address_lookup_state(address) {
let _ = self
.gas_tracker
self.gas_tracker
.apply_charge(self.price_list().on_resolve_address())?;
}
let id = self.state_tree().lookup_id(address)?;
Expand All @@ -436,8 +435,7 @@ where
fn get_actor(&self, id: ActorID) -> Result<Option<ActorState>> {
let access = self.state_access_tracker.get_actor_access_state(id);
if access < Some(ActorAccessState::Read) {
let _ = self
.gas_tracker
self.gas_tracker
.apply_charge(self.price_list().on_actor_lookup())?;
}
let actor = self.state_tree().get_actor(id)?;
Expand All @@ -448,13 +446,11 @@ where
fn set_actor(&mut self, id: ActorID, state: ActorState) -> Result<()> {
let access = self.state_access_tracker.get_actor_access_state(id);
if access < Some(ActorAccessState::Read) {
let _ = self
.gas_tracker
self.gas_tracker
.apply_charge(self.price_list().on_actor_lookup())?;
}
if access < Some(ActorAccessState::Updated) {
let _ = self
.gas_tracker
self.gas_tracker
.apply_charge(self.price_list().on_actor_update())?;
}
self.state_tree_mut().set_actor(id, state);
Expand All @@ -465,13 +461,11 @@ where
fn delete_actor(&mut self, id: ActorID) -> Result<()> {
let access = self.state_access_tracker.get_actor_access_state(id);
if access < Some(ActorAccessState::Read) {
let _ = self
.gas_tracker
self.gas_tracker
.apply_charge(self.price_list().on_actor_lookup())?;
}
if access < Some(ActorAccessState::Updated) {
let _ = self
.gas_tracker
self.gas_tracker
.apply_charge(self.price_list().on_actor_update())?;
}
self.state_tree_mut().delete_actor(id);
Expand Down Expand Up @@ -536,7 +530,7 @@ where
fn create_actor_from_send(&mut self, addr: &Address, act: ActorState) -> Result<ActorID> {
// This will charge for the address assignment and the actor storage, but not the actor
// lookup/update (charged below in `set_actor`).
let _ = self.charge_gas(self.price_list().on_create_actor(true))?;
self.charge_gas(self.price_list().on_create_actor(true))?;
let addr_id = self.state_tree_mut().register_new_address(addr)?;
self.state_access_tracker.record_lookup_address(addr);

Expand Down Expand Up @@ -778,7 +772,7 @@ where
});

// Process the result, updating the backtrace if necessary.
let ret = match result {
let mut ret = match result {
Ok(ret) => Ok(InvocationResult {
exit_code: ExitCode::OK,
value: ret.cloned(),
Expand Down Expand Up @@ -851,7 +845,9 @@ where
.price_list()
.on_method_return(cm.call_stack_depth, ret_size)
{
let _ = cm.charge_gas(charge);
if let Err(e) = cm.charge_gas(charge) {
ret = Err(e);
}
}
}

Expand Down
4 changes: 2 additions & 2 deletions fvm/src/gas/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -298,9 +298,9 @@ mod tests {
#[allow(clippy::identity_op)]
fn basic_gas_tracker() -> Result<()> {
let t = GasTracker::new(Gas::new(20), Gas::new(10), false);
let _ = t.apply_charge(GasCharge::new("", Gas::new(5), Gas::zero()))?;
t.apply_charge(GasCharge::new("", Gas::new(5), Gas::zero()))?;
assert_eq!(t.gas_used(), Gas::new(15));
let _ = t.apply_charge(GasCharge::new("", Gas::new(5), Gas::zero()))?;
t.apply_charge(GasCharge::new("", Gas::new(5), Gas::zero()))?;
assert_eq!(t.gas_used(), Gas::new(20));
assert!(t
.apply_charge(GasCharge::new("", Gas::new(1), Gas::zero()))
Expand Down
1 change: 0 additions & 1 deletion fvm/src/gas/timer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ pub type GasInstant = Instant;

/// A handle returned by `charge_gas` which must be used to mark the end of
/// the execution associated with that gas.
#[must_use]
#[derive(Debug)]
pub struct GasTimer(Option<GasTimerInner>);

Expand Down
8 changes: 3 additions & 5 deletions fvm/src/kernel/default.rs
Original file line number Diff line number Diff line change
Expand Up @@ -267,8 +267,7 @@ where
fn block_open(&mut self, cid: &Cid) -> Result<(BlockId, BlockStat)> {
// TODO(M2): Check for reachability here.

let _ = self
.call_manager
self.call_manager
.charge_gas(self.call_manager.price_list().on_block_open_base())?;

let start = GasTimer::start();
Expand Down Expand Up @@ -740,9 +739,8 @@ where
);
}

let _ = self
.call_manager
.charge_gas(self.call_manager.price_list().on_tipset_cid(offset > 1));
self.call_manager
.charge_gas(self.call_manager.price_list().on_tipset_cid(offset > 1))?;

self.call_manager.externs().get_tipset_cid(epoch).or_fatal()
}
Expand Down
2 changes: 1 addition & 1 deletion fvm/src/syscalls/bind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ fn memory_and_data<'a, K: Kernel>(
macro_rules! charge_syscall_gas {
($kernel:expr) => {
let charge = $kernel.price_list().on_syscall();
let _ = $kernel
$kernel
.charge_gas(&charge.name, charge.compute_gas)
.map_err(Abort::from_error_as_fatal)?;
};
Expand Down
5 changes: 2 additions & 3 deletions fvm/src/syscalls/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,7 @@ pub fn charge_for_exec<K: Kernel>(
// Only recording time for the execution, not for the memory part, which is unknown. But we
// could perform stomething like a multi-variate linear regression to see if the amount of
// memory explains any of the exectuion time.
let _ = data
.kernel
data.kernel
.charge_gas("wasm_memory_grow", memory_gas_charge)
.map_err(Abort::from_error_as_fatal)?;
}
Expand All @@ -179,7 +178,7 @@ pub fn charge_for_init<K: Kernel>(

if let Some(min_table_elements) = min_table_elements(module) {
let table_gas = data.kernel.price_list().init_table_gas(min_table_elements);
let _ = data.kernel.charge_gas("wasm_table_init", table_gas)?;
data.kernel.charge_gas("wasm_table_init", table_gas)?;
}

data.kernel.charge_gas("wasm_memory_init", memory_gas)
Expand Down
Loading