Skip to content

Commit

Permalink
Added WASM execution unit base for better costing.
Browse files Browse the repository at this point in the history
  • Loading branch information
lrubasze committed Oct 29, 2024
1 parent a1f8e7b commit 86828df
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 7 deletions.
22 changes: 19 additions & 3 deletions radix-engine/src/system/system_modules/costing/fee_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,9 +176,25 @@ impl FeeTable {
_export_name: &str,
wasm_execution_units: u32,
) -> u32 {
// From `costing::spin_loop`, it takes 5.5391 ms for 1918122691 wasm execution units.
// Therefore, cost for single unit: 5.5391 * 1000 / 1918122691 * 100 = 0.00028877714

// W - WASM execution units
// C - cost units
// c - single cost unit
// T - execution time (1 µs = 100 c => 1 ms = 100,000 c)
//
// Cost units might be expressed as
// C = T * c
//
// To convert W to C, we need a d.
// C = W / divider
// divider = W / C
// divider = W / (T * c)
//
// From `costing::spin_loop_v2`, it takes T=960 ms to consume W=274,517,401,207 wasm execution
// units (measured at GH benchmark, git rev 1fd85c47ef, EC2 instance type c6a.4xlarge).
// T = 960 ms = 960 * 100,000
// W = 274,517,401,207
// Therefore
// divider = 274,517,401,207 / (960 * 100,000) = 2859.556 ~= 3000
wasm_execution_units / 3000
}

Expand Down
23 changes: 19 additions & 4 deletions radix-engine/src/vm/wasm_runtime/scrypto_runtime.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use core::u32;

use crate::errors::InvokeError;
use crate::errors::RuntimeError;
use crate::internal_prelude::*;
Expand All @@ -21,6 +23,7 @@ pub struct ScryptoRuntime<'y, Y: SystemApi<RuntimeError>> {
export_name: String,
wasm_execution_units_buffer: u32,
scrypto_vm_version: ScryptoVmVersion,
wasm_execution_units_base: u32,
}

impl<'y, Y: SystemApi<RuntimeError>> ScryptoRuntime<'y, Y> {
Expand All @@ -30,6 +33,16 @@ impl<'y, Y: SystemApi<RuntimeError>> ScryptoRuntime<'y, Y> {
export_name: String,
scrypto_vm_version: ScryptoVmVersion,
) -> Self {
let wasm_execution_units_base = if scrypto_vm_version < ScryptoVmVersion::cuttlefish() {
0
} else {
// Add 7,000 base units to make sure the we do not undercharge for WASM execution,
// which might lead to system exploitation.
// This is especially important in corner-cases such as `costing::spin_loop_v2` benchmark.
// less frequently.
7000
};

ScryptoRuntime {
api,
buffers: index_map_new(),
Expand All @@ -38,9 +51,9 @@ impl<'y, Y: SystemApi<RuntimeError>> ScryptoRuntime<'y, Y> {
export_name,
wasm_execution_units_buffer: 0,
scrypto_vm_version,
wasm_execution_units_base,
}
}

pub fn parse_blueprint_id(
package_address: Vec<u8>,
blueprint_name: Vec<u8>,
Expand All @@ -59,9 +72,9 @@ impl<'y, Y: SystemApi<RuntimeError>> ScryptoRuntime<'y, Y> {
) -> Result<(), InvokeError<WasmRuntimeError>> {
assert!(n > self.wasm_execution_units_buffer);
let n_remaining_after_buffer_used = n - self.wasm_execution_units_buffer;
let amount_to_request = n_remaining_after_buffer_used
.checked_add(WASM_EXECUTION_COST_UNITS_BUFFER)
.unwrap_or(u32::MAX);
let amount_to_request =
n_remaining_after_buffer_used.saturating_add(WASM_EXECUTION_COST_UNITS_BUFFER);

self.api
.consume_cost_units(ClientCostingEntry::RunWasmCode {
package_address: &self.package_address,
Expand Down Expand Up @@ -401,6 +414,8 @@ impl<'y, Y: SystemApi<RuntimeError>> WasmRuntime for ScryptoRuntime<'y, Y> {
&mut self,
n: u32,
) -> Result<(), InvokeError<WasmRuntimeError>> {
let n = n.saturating_add(self.wasm_execution_units_base);

if n <= self.wasm_execution_units_buffer {
self.wasm_execution_units_buffer -= n;
Ok(())
Expand Down

0 comments on commit 86828df

Please sign in to comment.