Skip to content

Commit

Permalink
Switch to wasmi native fuel metering
Browse files Browse the repository at this point in the history
  • Loading branch information
jayz22 committed May 19, 2023
1 parent 87f0aa1 commit 4a0d043
Show file tree
Hide file tree
Showing 10 changed files with 270 additions and 123 deletions.
49 changes: 23 additions & 26 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 7 additions & 8 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,16 @@ rev = "b283ec0bcb791610013107b9eab7d7ff07a65db1"
default-features = false

[workspace.dependencies.wasmi]
package = "wasmi"
version = "0.29.0"
git = "https://github.com/paritytech/wasmi"
rev = "23d8d8c684255f2d63526baa348ab3eb3d249de0"
package = "soroban-wasmi"
# version = "0.16.0-soroban2"
git = "https://github.com/stellar/wasmi"
# rev = "862b32f5"

# [patch."https://github.com/stellar/rs-stellar-xdr"]
# stellar-xdr = { path = "../rs-stellar-xdr/" }

# [patch."https://github.com/stellar/wasmi"]
# soroban-wasmi = { path = "../wasmi/wasmi_v1/" }
# soroban-wasmi_core = { path = "../wasmi/core/" }
[patch."https://github.com/stellar/wasmi"]
soroban-wasmi = { path = "../wasmi/crates/wasmi/" }
soroban-wasmi_core = { path = "../wasmi/crates/core/" }

[profile.release]
codegen-units = 1
Expand Down
33 changes: 31 additions & 2 deletions soroban-env-host/src/budget.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,10 @@ impl BudgetDimension {
self.limit
}

pub fn get_remaining(&self) -> u64 {
self.limit.saturating_sub(self.total_count)
}

pub fn reset(&mut self, limit: u64) {
self.limit = limit;
self.total_count = 0;
Expand Down Expand Up @@ -185,6 +189,17 @@ impl BudgetDimension {
}
}

pub fn apply_fuel(&mut self, amount: u64) -> Result<(), HostError> {
let ty = ContractCostType::WasmInsnExec;
self.counts[ty as usize] = self.counts[ty as usize].saturating_add(amount);
self.total_count = self.total_count.saturating_add(amount);
if self.is_over_budget() {
Err((ScErrorType::Budget, ScErrorCode::ExceededLimit).into())
} else {
Ok(())
}
}

// Resets all model parameters to zero (so that we can override and test individual ones later).
#[cfg(test)]
pub fn reset_models(&mut self) {
Expand Down Expand Up @@ -450,6 +465,12 @@ impl Budget {
self.charge_in_bulk(ty, 1, input)
}

pub fn apply_fuel(&self, amount: u64) -> Result<(), HostError> {
self.mut_budget(|mut b| b.cpu_insns.apply_fuel(amount))
// TODO: ignored mem bytes
// TODO: ignored tracker
}

/// Performs a bulk charge to the budget under the specified [`CostType`].
/// The `iterations` is the batch size. The caller needs to ensure:
/// 1. the batched charges have identical costs (having the same
Expand Down Expand Up @@ -496,14 +517,22 @@ impl Budget {
f(&mut self.0.borrow_mut().tracker[ty as usize])
}

pub fn get_cpu_insns_count(&self) -> u64 {
pub fn get_cpu_insns_consumed(&self) -> u64 {
self.0.borrow().cpu_insns.get_total_count()
}

pub fn get_mem_bytes_count(&self) -> u64 {
pub fn get_mem_bytes_consumed(&self) -> u64 {
self.0.borrow().mem_bytes.get_total_count()
}

pub fn get_cpu_insns_remaining(&self) -> u64 {
self.0.borrow().cpu_insns.get_remaining()
}

pub fn get_mem_bytes_remaining(&self) -> u64 {
self.0.borrow().mem_bytes.get_remaining()
}

pub fn reset_default(&self) {
*self.0.borrow_mut() = BudgetImpl::default()
}
Expand Down
8 changes: 6 additions & 2 deletions soroban-env-host/src/host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,13 +205,17 @@ impl Host {
/// Helper for mutating the [`Budget`] held in this [`Host`], either to
/// allocate it on contract creation or to deplete it on callbacks from
/// the VM or host functions.
pub fn with_budget<T, F>(&self, f: F) -> T
pub(crate) fn with_budget<T, F>(&self, f: F) -> Result<T, HostError>
where
F: FnOnce(Budget) -> T,
F: FnOnce(Budget) -> Result<T, HostError>,
{
f(self.0.budget.clone())
}

// pub (crate) fn with_mut_budget<T, F>(&self, mut f: F) -> Result<T, HostError>
// where
// F: FnMut()

pub(crate) fn budget_ref(&self) -> &Budget {
&self.0.budget
}
Expand Down
9 changes: 9 additions & 0 deletions soroban-env-host/src/host/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,15 @@ impl Host {
)
}

pub(crate) fn err_wasmi_fuel_metering_disabled(&self) -> HostError {
self.err(
ScErrorType::WasmVm,
ScErrorCode::InternalError,
"wasmi fuel metering is disabled",
&[],
)
}

/// Given a result carrying some error type that can be converted to an
/// [Error] and supports [core::fmt::Debug], calls [Host::error] with the
/// error when there's an error, also passing the result of
Expand Down
23 changes: 14 additions & 9 deletions soroban-env-host/src/test/budget_metering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,10 @@ fn xdr_object_conversion() -> Result<(), HostError> {
// we wind up double-counting the conversion of "objects".
// Possibly this should be improved in the future.
assert_eq!(budget.get_tracker(ContractCostType::ValXdrConv).0, 6);
assert_eq!(budget.get_cpu_insns_count(), 60);
assert_eq!(budget.get_mem_bytes_count(), 6);
});
assert_eq!(budget.get_cpu_insns_consumed(), 60);
assert_eq!(budget.get_mem_bytes_consumed(), 6);
Ok(())
})?;
Ok(())
}

Expand All @@ -63,9 +64,10 @@ fn vm_hostfn_invocation() -> Result<(), HostError> {
budget.get_tracker(ContractCostType::InvokeHostFunction).0,
2
);
assert_eq!(budget.get_cpu_insns_count(), 30);
assert_eq!(budget.get_mem_bytes_count(), 3);
});
assert_eq!(budget.get_cpu_insns_consumed(), 30);
assert_eq!(budget.get_mem_bytes_consumed(), 3);
Ok(())
})?;

Ok(())
}
Expand Down Expand Up @@ -96,15 +98,17 @@ fn metered_xdr() -> Result<(), HostError> {
budget.get_tracker(ContractCostType::ValSer).1,
Some(w.len() as u64)
);
});
Ok(())
})?;

host.metered_from_xdr::<ScMap>(w.as_slice())?;
host.with_budget(|budget| {
assert_eq!(
budget.get_tracker(ContractCostType::ValDeser).1,
Some(w.len() as u64)
);
});
Ok(())
})?;
Ok(())
}

Expand Down Expand Up @@ -155,7 +159,8 @@ fn map_insert_key_vec_obj() -> Result<(), HostError> {
assert_eq!(budget.get_tracker(ContractCostType::VisitObject).0, 4);
// upper bound of number of map-accesses, counting both binary-search and point-access.
assert_eq!(budget.get_tracker(ContractCostType::MapEntry).0, 5);
});
Ok(())
})?;

Ok(())
}
Expand Down
4 changes: 2 additions & 2 deletions soroban-env-host/src/test/hostile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,8 @@ fn hostile_objs_traps() -> Result<(), HostError> {
let args: ScVec = host.test_scvec::<i32>(&[])?;

host.set_diagnostic_level(crate::DiagnosticLevel::Debug);
host.with_budget(|b| b.reset_default());
host.with_budget(|b| b.reset_unlimited_cpu());
host.with_budget(|b| Ok(b.reset_default()))?;
host.with_budget(|b| Ok(b.reset_unlimited_cpu()))?;

// This one should just run out of memory
let res = vm.invoke_function(&host, "objs", &args);
Expand Down
8 changes: 6 additions & 2 deletions soroban-env-host/src/test/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,9 @@ impl Host {
self.with_budget(|budget| {
budget.reset_limits(cpu, mem); // something big but finite that we may exceed
budget.reset_models();
});
Ok(())
})
.unwrap();
self
}

Expand Down Expand Up @@ -101,7 +103,9 @@ impl Host {
.mem_bytes
.get_cost_model_mut(ty)
.linear_term = lin_mem as i64;
});
Ok(())
})
.unwrap();
self
}

Expand Down
Loading

0 comments on commit 4a0d043

Please sign in to comment.