Skip to content

Commit 7bf6731

Browse files
authored
Merge pull request #501 from filecoin-project/asr/gas-fix
fix: gas: charge for execunits based on snapshot
2 parents 70e7697 + f4e4ebe commit 7bf6731

File tree

6 files changed

+33
-28
lines changed

6 files changed

+33
-28
lines changed

fvm/src/call_manager/default.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::cmp::max;
2+
13
use anyhow::Context;
24
use derive_more::{Deref, DerefMut};
35
use fvm_ipld_encoding::{RawBytes, DAG_CBOR};
@@ -314,6 +316,7 @@ where
314316
// it returns a referenced copy.
315317
let engine = self.engine().clone();
316318

319+
let gas_available = self.gas_tracker.gas_available();
317320
log::trace!("calling {} -> {}::{}", from, to, method);
318321
self.map_mut(|cm| {
319322
// Make the kernel.
@@ -331,10 +334,12 @@ where
331334
};
332335

333336
// Make a store.
334-
let gas_available = kernel.gas_available();
337+
let gas_used = kernel.gas_used();
335338
let exec_units_to_add = match kernel.network_version() {
336339
NetworkVersion::V14 | NetworkVersion::V15 => i64::MAX,
337-
_ => kernel.price_list().gas_to_exec_units(gas_available, false),
340+
_ => kernel
341+
.price_list()
342+
.gas_to_exec_units(max(gas_available.saturating_sub(gas_used), 0), false),
338343
};
339344

340345
let mut store = engine.new_store(kernel);

fvm/src/kernel/default.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -751,8 +751,8 @@ impl<C> GasOps for DefaultKernel<C>
751751
where
752752
C: CallManager,
753753
{
754-
fn gas_available(&self) -> i64 {
755-
self.call_manager.gas_tracker().gas_available()
754+
fn gas_used(&self) -> i64 {
755+
self.call_manager.gas_tracker().gas_used()
756756
}
757757

758758
fn charge_gas(&mut self, name: &str, compute: i64) -> Result<()> {

fvm/src/kernel/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -219,8 +219,8 @@ pub trait CircSupplyOps {
219219
/// In the future (Phase 1), this should disappear and be replaced by gas instrumentation
220220
/// at the WASM level.
221221
pub trait GasOps {
222-
/// GasAvailable return the gas available for the transaction.
223-
fn gas_available(&self) -> i64;
222+
/// GasUsed return the gas used by the transaction so far.
223+
fn gas_used(&self) -> i64;
224224

225225
/// ChargeGas charges specified amount of `gas` for execution.
226226
/// `name` provides information about gas charging point

fvm/src/syscalls/bind.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -106,13 +106,11 @@ fn charge_exec_units_for_gas(caller: &mut Caller<InvocationData<impl Kernel>>) -
106106
caller.consume_fuel(u64::try_from(exec_units).unwrap_or(0))?;
107107
}
108108

109-
let gas_available = caller.data().kernel.gas_available();
109+
let gas_used = caller.data().kernel.gas_used();
110110
let fuel_consumed = caller
111111
.fuel_consumed()
112112
.ok_or_else(|| Trap::new("expected to find exec_units consumed"))?;
113-
caller
114-
.data_mut()
115-
.set_snapshots(gas_available, fuel_consumed);
113+
caller.data_mut().set_snapshots(gas_used, fuel_consumed);
116114
Ok(())
117115
}
118116

fvm/src/syscalls/mod.rs

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,10 @@ pub struct InvocationData<K> {
3131
/// after receiving this error without calling any other syscalls.
3232
pub last_error: Option<backtrace::Cause>,
3333

34-
/// This snapshot is used to track changes in available_gas during syscall invocations.
34+
/// This snapshot is used to track changes in gas_used during syscall invocations.
3535
/// The snapshot gets taken when execution exits WASM _after_ charging gas for any newly incurred fuel costs.
36-
/// When execution moves back into WASM, we consume fuel for the delta between the snapshot and the new gas_available value.
37-
pub gas_available_snapshot: i64,
36+
/// When execution moves back into WASM, we consume fuel for the delta between the snapshot and the new gas_used value.
37+
pub gas_used_snapshot: i64,
3838

3939
/// This snapshot is used to track changes in fuel_consumed during WASM execution.
4040
/// The snapshot gets taken when execution enters WASM _after_ consuming fuel for any syscall gas consumption.
@@ -44,46 +44,48 @@ pub struct InvocationData<K> {
4444

4545
impl<K: Kernel> InvocationData<K> {
4646
pub(crate) fn new(kernel: K) -> Self {
47-
let gas_available = kernel.gas_available();
47+
let gas_used = kernel.gas_used();
4848
Self {
4949
kernel,
5050
last_error: None,
51-
gas_available_snapshot: gas_available,
51+
gas_used_snapshot: gas_used,
5252
exec_units_consumed_snapshot: 0,
5353
}
5454
}
5555

5656
/// This method:
57-
/// 1) calculates the available_gas delta from the previous snapshot,
58-
/// 2) converts this to the corresponding amount of exec_units
59-
/// 3) updates the available_gas and exec_units_consumed snapshots. The exec_units_consumed_snapshot is optimistically updated, assuming the value calculated in 2 will be consumed
60-
/// 4) returns the value calculated in 2) for its caller to actually consume that exec_units_consumed
57+
/// 1) calculates the gas_used delta from the previous snapshot,
58+
/// 2) converts this to the corresponding amount of exec_units.
59+
/// 3) returns the value calculated in 2) for its caller to actually consume that exec_units_consumed
60+
/// The caller should also update the snapshots after doing so.
6161
pub(crate) fn calculate_exec_units_for_gas(&self) -> Result<i64> {
62-
let gas_available = self.kernel.gas_available();
62+
let gas_used = self.kernel.gas_used();
6363
let exec_units_to_consume = self
6464
.kernel
6565
.price_list()
66-
.gas_to_exec_units(self.gas_available_snapshot - gas_available, true);
66+
.gas_to_exec_units(gas_used - self.gas_used_snapshot, true);
6767
Ok(exec_units_to_consume)
6868
}
6969

70-
pub(crate) fn set_snapshots(&mut self, gas_available: i64, exec_units_consumed: u64) {
71-
self.gas_available_snapshot = gas_available;
70+
pub(crate) fn set_snapshots(&mut self, gas_used: i64, exec_units_consumed: u64) {
71+
self.gas_used_snapshot = gas_used;
7272
self.exec_units_consumed_snapshot = exec_units_consumed;
7373
}
7474

7575
/// This method:
7676
/// 1) charges gas corresponding to the exec_units_consumed delta based on the previous snapshot
77-
/// 2) updates the exec_units_consumed and gas_available snapshots
77+
/// 2) updates the exec_units_consumed and gas_used snapshots
7878
pub(crate) fn charge_gas_for_exec_units(&mut self, exec_units_consumed: u64) -> Result<()> {
7979
self.kernel.charge_gas(
8080
"exec_units",
8181
self.kernel
8282
.price_list()
83-
.on_consume_exec_units(exec_units_consumed)
83+
.on_consume_exec_units(
84+
exec_units_consumed.saturating_sub(self.exec_units_consumed_snapshot),
85+
)
8486
.total(),
8587
)?;
86-
self.set_snapshots(self.kernel.gas_available(), exec_units_consumed);
88+
self.set_snapshots(self.kernel.gas_used(), exec_units_consumed);
8789
Ok(())
8890
}
8991
}

testing/conformance/src/vm.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -488,8 +488,8 @@ where
488488
C: CallManager<Machine = TestMachine<M>>,
489489
K: Kernel<CallManager = TestCallManager<C>>,
490490
{
491-
fn gas_available(&self) -> i64 {
492-
self.0.gas_available()
491+
fn gas_used(&self) -> i64 {
492+
self.0.gas_used()
493493
}
494494

495495
fn charge_gas(&mut self, name: &str, compute: i64) -> Result<()> {

0 commit comments

Comments
 (0)