diff --git a/radix-common/src/constants/transaction_execution.rs b/radix-common/src/constants/transaction_execution.rs index a3af1cfb2c..a76d224b75 100644 --- a/radix-common/src/constants/transaction_execution.rs +++ b/radix-common/src/constants/transaction_execution.rs @@ -124,6 +124,3 @@ pub const USD_PRICE_IN_XRD: &str = "16.666666666666666666"; /// The maximum that a package or component owner is allowed to set their method royalty to. 10 USD pub const MAX_PER_FUNCTION_ROYALTY_IN_XRD: &str = "166.666666666666666666"; - -/// The maximum number of "live" buffers maintained by Scrypto runtime. -pub const MAX_NUMBER_OF_BUFFERS: usize = 32; diff --git a/radix-engine-tests/assets/blueprints/Cargo.lock b/radix-engine-tests/assets/blueprints/Cargo.lock index 1ed4f50708..529debe840 100644 --- a/radix-engine-tests/assets/blueprints/Cargo.lock +++ b/radix-engine-tests/assets/blueprints/Cargo.lock @@ -1331,6 +1331,13 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasm_limits" +version = "1.0.0" +dependencies = [ + "scrypto", +] + [[package]] name = "wasm_non_mvp" version = "1.0.0" diff --git a/radix-engine-tests/assets/blueprints/Cargo.toml b/radix-engine-tests/assets/blueprints/Cargo.toml index 7b9006f815..6295dc7c83 100644 --- a/radix-engine-tests/assets/blueprints/Cargo.toml +++ b/radix-engine-tests/assets/blueprints/Cargo.toml @@ -80,6 +80,7 @@ members = [ "oracles/oracle_v3", "steal", "locker-factory", + "wasm_limits", ] resolver = "2" diff --git a/radix-engine-tests/assets/blueprints/wasm_limits/Cargo.toml b/radix-engine-tests/assets/blueprints/wasm_limits/Cargo.toml new file mode 100644 index 0000000000..adb2d8c5da --- /dev/null +++ b/radix-engine-tests/assets/blueprints/wasm_limits/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "wasm_limits" +version = "1.0.0" +edition = "2021" + +[dependencies] +scrypto = { path = "../../../../scrypto" } + +[lib] +crate-type = ["cdylib", "lib"] diff --git a/radix-engine-tests/assets/blueprints/wasm_limits/src/lib.rs b/radix-engine-tests/assets/blueprints/wasm_limits/src/lib.rs new file mode 100644 index 0000000000..85565f7f1f --- /dev/null +++ b/radix-engine-tests/assets/blueprints/wasm_limits/src/lib.rs @@ -0,0 +1,14 @@ +use scrypto::prelude::*; + +#[blueprint] +mod wasm_limits { + struct WasmLimits {} + + impl WasmLimits { + pub fn create_buffers(n: usize) { + for _ in 0..n { + let _ = unsafe { wasm_api::actor::actor_get_blueprint_name() }; + } + } + } +} diff --git a/radix-engine-tests/tests/vm/mod.rs b/radix-engine-tests/tests/vm/mod.rs index 2248938094..307768bf58 100644 --- a/radix-engine-tests/tests/vm/mod.rs +++ b/radix-engine-tests/tests/vm/mod.rs @@ -14,6 +14,7 @@ mod scrypto_validation; mod scrypto_validator; mod stack_size; mod system_wasm_buffers; +mod wasm_limits; mod wasm_memory; mod wasm_metering; mod wasm_non_mvp; diff --git a/radix-engine-tests/tests/vm/wasm_limits.rs b/radix-engine-tests/tests/vm/wasm_limits.rs new file mode 100644 index 0000000000..86498076b2 --- /dev/null +++ b/radix-engine-tests/tests/vm/wasm_limits.rs @@ -0,0 +1,43 @@ +use radix_engine_tests::common::PackageLoader; +use scrypto_test::prelude::*; + +#[test] +fn test_create_buffers_within_limits() { + // Arrange + let mut ledger = LedgerSimulatorBuilder::new().build(); + let package = ledger.publish_package_simple(PackageLoader::get("wasm_limits")); + + let manifest = ManifestBuilder::new() + .lock_fee_from_faucet() + .call_function(package, "WasmLimits", "create_buffers", (4usize,)) + .build(); + + // Act + let receipt = ledger.execute_manifest(manifest, vec![]); + + // Assert + receipt.expect_commit_success(); +} + +#[test] +fn test_crate_buffers_beyond_limits() { + // Arrange + let mut ledger = LedgerSimulatorBuilder::new().build(); + let package = ledger.publish_package_simple(PackageLoader::get("wasm_limits")); + + let manifest = ManifestBuilder::new() + .lock_fee_from_faucet() + .call_function(package, "WasmLimits", "create_buffers", (5usize,)) + .build(); + + // Act + let receipt = ledger.execute_manifest(manifest, vec![]); + + // Assert + receipt.expect_specific_failure(|runtime_error| { + matches!( + runtime_error, + RuntimeError::VmError(VmError::Wasm(WasmRuntimeError::TooManyBuffers)) + ) + }) +} diff --git a/radix-engine/src/vm/wasm_runtime/scrypto_runtime.rs b/radix-engine/src/vm/wasm_runtime/scrypto_runtime.rs index 711418de05..af4d953a47 100644 --- a/radix-engine/src/vm/wasm_runtime/scrypto_runtime.rs +++ b/radix-engine/src/vm/wasm_runtime/scrypto_runtime.rs @@ -20,7 +20,6 @@ pub struct ScryptoRuntime<'y, Y: SystemApi> { package_address: PackageAddress, export_name: String, wasm_execution_units_buffer: u32, - max_number_of_buffers: usize, scrypto_vm_version: ScryptoVmVersion, } @@ -38,7 +37,6 @@ impl<'y, Y: SystemApi> ScryptoRuntime<'y, Y> { package_address, export_name, wasm_execution_units_buffer: 0, - max_number_of_buffers: MAX_NUMBER_OF_BUFFERS, scrypto_vm_version, } } @@ -83,7 +81,14 @@ impl<'y, Y: SystemApi> WasmRuntime for ScryptoRuntime<'y, Y> { ) -> Result> { assert!(buffer.len() <= 0xffffffff); - if self.buffers.len() >= self.max_number_of_buffers { + let max_number_of_buffers = match self.scrypto_vm_version { + ScryptoVmVersion::V1_0 | ScryptoVmVersion::V1_1 => 32, + // Practically speaking, there is little gain of keeping multiple buffers open before + // [multi-value](https://github.com/WebAssembly/multi-value/blob/master/proposals/multi-value/Overview.md) is supported and used. + // We reduce it to `4` so that the amount of memory that a transaction can consume is reduced, which is beneficial for parallel execution. + ScryptoVmVersion::V1_2 => 4, + }; + if self.buffers.len() >= max_number_of_buffers { return Err(InvokeError::SelfError(WasmRuntimeError::TooManyBuffers)); }