Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Commit

Permalink
update tests and fix bugs
Browse files Browse the repository at this point in the history
tests::run_out_of_gas_engine, need 2 more

save: 2 bugs with gas syncs: 1 of 2 tests done

gas_syncs_no_overcharge bug fixed, test passes!

cleaned out debug prints

second bug is not a bug

disabled_chain_extension test fix (err msg)

tests run_out_of_fuel_host, chain_extension pass

all tests pass
  • Loading branch information
agryaznov committed Jun 11, 2023
1 parent c25f634 commit 7f46e7e
Show file tree
Hide file tree
Showing 6 changed files with 257 additions and 49 deletions.
10 changes: 7 additions & 3 deletions frame/contracts/proc-macro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -680,16 +680,20 @@ fn expand_functions(def: &EnvDef, expand_blocks: bool, host_state: TokenStream2)
quote! {
let __gas_before__ = {
let engine_consumed = __caller__.fuel_consumed().expect("Fuel metering is enabled; qed");
__caller__.data_mut().ext().gas_meter_mut().charge_fuel(engine_consumed).map_err(#into_trap).map_err(#into_host)?.ref_time()
let gas_meter = __caller__.data_mut().ext().gas_meter_mut();
let fuel_to_charge = engine_consumed.saturating_sub(gas_meter.engine_consumed());
gas_meter.sync_fuel(fuel_to_charge).map_err(#into_trap).map_err(#into_host)?.ref_time()
};
}
} else {
quote! { }
};
let sync_gas_after = if expand_blocks {
quote! {
let gas_after = __caller__.data_mut().ext().gas_meter().gas_left().ref_time();
let host_consumed = __gas_before__.saturating_sub(gas_after);
let mut gas_after = __caller__.data_mut().ext().gas_meter().gas_left().ref_time();
let mut host_consumed = __gas_before__.saturating_sub(gas_after);
// Possible undercharge of at max 1 fuel here, if host consumed less than `instruction_weights.base`
// Not a problem though, as soon as host accounts its spent gas properly.
let fuel_consumed = host_consumed.checked_div(__caller__.data_mut().ext().schedule().instruction_weights.base as u64).ok_or(Error::<E::T>::InvalidSchedule).map_err(#into_trap).map_err(#into_host)?;
__caller__.consume_fuel(fuel_consumed).map_err(|_| TrapReason::from(Error::<E::T>::OutOfGas)).map_err(#into_host)?;
}
Expand Down
30 changes: 22 additions & 8 deletions frame/contracts/src/gas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ pub struct GasMeter<T: Config> {
gas_left: Weight,
/// Due to `adjust_gas` and `nested` the `gas_left` can temporarily dip below its final value.
gas_left_lowest: Weight,
/// Amount of fuel consumed by the engine from the last host function call.
engine_consumed: u64,
_phantom: PhantomData<T>,
#[cfg(test)]
tokens: Vec<ErasedToken>,
Expand All @@ -92,6 +94,7 @@ impl<T: Config> GasMeter<T> {
gas_limit,
gas_left: gas_limit,
gas_left_lowest: gas_limit,
engine_consumed: Default::default(),
_phantom: PhantomData,
#[cfg(test)]
tokens: Vec::new(),
Expand Down Expand Up @@ -154,6 +157,8 @@ impl<T: Config> GasMeter<T> {
/// Returns `OutOfGas` if there is not enough gas or addition of the specified
/// amount of gas has lead to overflow. On success returns `Proceed`.
///
/// Any charged amount less than base instruction weight is rounded up to it.
///
/// NOTE that amount isn't consumed if there is not enough gas. This is considered
/// safe because we always charge gas before performing any resource-spending action.
#[inline]
Expand Down Expand Up @@ -182,24 +187,28 @@ impl<T: Config> GasMeter<T> {
self.gas_left = self.gas_left.saturating_add(adjustment).min(self.gas_limit);
}

/// Charge self with the `ref_time` Weight corresponding to `wasmi_fuel` consumed on the engine
/// This method is used for gas syncs with the engine in every host function.
///
/// Updates internal `engine_comsumed` tracker of engine fuel consumption.
///
/// Charges self with the `ref_time` Weight corresponding to `wasmi_fuel` consumed on the engine
/// side. Passed value is scaled by multiplying it by the weight of a basic operation, as such
/// an operation in wasmi engine costs 1.
///
/// This is used for gas syncs with the engine in every host function.
///
/// Returns the updated gas_left Weight value from the meter.
/// Returns the updated `gas_left` Weight value from the meter.
/// Normally this would never fail, as engine should fail first when out of gas.
pub fn charge_fuel(&mut self, wasmi_fuel: u64) -> Result<Weight, DispatchError> {
let ref_time = self.gas_left.ref_time_mut();
pub fn sync_fuel(&mut self, wasmi_fuel: u64) -> Result<Weight, DispatchError> {
if !wasmi_fuel.is_zero() {
self.engine_consumed += wasmi_fuel;
let reftime_consumed =
wasmi_fuel.saturating_mul(T::Schedule::get().instruction_weights.base as u64);
*ref_time = self
.gas_limit
let ref_time_left = self
.gas_left
.ref_time()
.checked_sub(reftime_consumed)
.ok_or_else(|| Error::<T>::OutOfGas)?;

*(self.gas_left.ref_time_mut()) = ref_time_left;
}
Ok(self.gas_left)
}
Expand All @@ -222,6 +231,11 @@ impl<T: Config> GasMeter<T> {
self.gas_left
}

/// Returns current tracked engine fuel consumption.
pub fn engine_consumed(&self) -> u64 {
self.engine_consumed
}

/// Turn this GasMeter into a DispatchResult that contains the actually used gas.
pub fn into_dispatch_result<R, E>(
self,
Expand Down
4 changes: 3 additions & 1 deletion frame/contracts/src/schedule.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ use sp_std::marker::PhantomData;
/// .. Default::default()
/// },
/// instruction_weights: InstructionWeights {
/// version: 5,
/// .. Default::default()
/// },
/// .. Default::default()
Expand Down Expand Up @@ -164,6 +163,9 @@ impl Limits {
#[derive(Clone, Encode, Decode, PartialEq, Eq, ScheduleDebug, TypeInfo)]
#[scale_info(skip_type_params(T))]
pub struct InstructionWeights<T: Config> {
/// Base instruction ref_time weight.
/// Used to gas units scaling between host and engine.
/// Should match to wasmi's 1 fuel (see <https://github.com/paritytech/wasmi/issues/701>).
pub base: u32,
/// The type parameter is used in the default implementation.
#[codec(skip)]
Expand Down

0 comments on commit 7f46e7e

Please sign in to comment.