diff --git a/Cargo.lock b/Cargo.lock index f70c9ee664c..70bd5e2e643 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2579,7 +2579,7 @@ dependencies = [ [[package]] name = "massa-sc-runtime" version = "0.10.0" -source = "git+https://github.com/massalabs/massa-sc-runtime?rev=80352eb9f2a6b90a441cd64433d8874c33fb384f#80352eb9f2a6b90a441cd64433d8874c33fb384f" +source = "git+https://github.com/massalabs/massa-sc-runtime?branch=add_condom#9a62f0b423244c7fe33fa8c6fdd6ad9d20a49aa9" dependencies = [ "anyhow", "as-ffi-bindings", diff --git a/Cargo.toml b/Cargo.toml index feaaee062ea..e59676cae56 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -107,7 +107,7 @@ massa_wallet = { path = "./massa-wallet" } # Massa projects dependencies massa-proto-rs = { git = "https://github.com/massalabs/massa-proto-rs", "rev" = "38950875a7aa406fedc4f0b8336864e5ff290f2c" } -massa-sc-runtime = { git = "https://github.com/massalabs/massa-sc-runtime", "rev" = "80352eb9f2a6b90a441cd64433d8874c33fb384f" } +massa-sc-runtime = { git = "https://github.com/massalabs/massa-sc-runtime", "branch" = "add_condom" } peernet = { git = "https://github.com/massalabs/PeerNet", "rev" = "04b05ddd320fbe76cc858115af7b5fc28bdb8310" } # Common dependencies diff --git a/massa-execution-exports/src/settings.rs b/massa-execution-exports/src/settings.rs index 49ae83b4559..03c4bd581ad 100644 --- a/massa-execution-exports/src/settings.rs +++ b/massa-execution-exports/src/settings.rs @@ -102,4 +102,6 @@ pub struct ExecutionConfig { pub max_execution_traces_slot_limit: usize, /// Where to dump blocks pub block_dump_folder_path: PathBuf, + /// Max runtime module exports + pub max_runtime_module_exports: usize, } diff --git a/massa-execution-worker/src/execution.rs b/massa-execution-worker/src/execution.rs index e884a58f145..4bc65b4e9e1 100644 --- a/massa-execution-worker/src/execution.rs +++ b/massa-execution-worker/src/execution.rs @@ -179,6 +179,7 @@ impl ExecutionState { hd_cache_size: config.hd_cache_size, snip_amount: config.snip_amount, max_module_length: config.max_bytecode_size, + max_runtime_module_exports: config.max_runtime_module_exports, }))); // Create an empty placeholder execution context, with shared atomic access @@ -970,6 +971,7 @@ impl ExecutionState { module, *max_gas, self.config.gas_costs.clone(), + self.config.max_runtime_module_exports, ) .map_err(|error| ExecutionError::VMError { context: "ExecuteSC".to_string(), @@ -1070,6 +1072,7 @@ impl ExecutionState { param, max_gas, self.config.gas_costs.clone(), + self.config.max_runtime_module_exports, ); match response { Ok(Response { init_gas_cost, .. }) @@ -1195,6 +1198,7 @@ impl ExecutionState { &message.function_params, message.max_gas, self.config.gas_costs.clone(), + self.config.max_runtime_module_exports, ); match response { Ok(res) => { @@ -1824,6 +1828,7 @@ impl ExecutionState { module, req.max_gas, self.config.gas_costs.clone(), + self.config.max_runtime_module_exports, ) .map_err(|error| ExecutionError::VMError { context: "ReadOnlyExecutionTarget::BytecodeExecution".to_string(), @@ -1878,6 +1883,7 @@ impl ExecutionState { ¶meter, req.max_gas, self.config.gas_costs.clone(), + self.config.max_runtime_module_exports, ); match response { diff --git a/massa-execution-worker/src/interface_impl.rs b/massa-execution-worker/src/interface_impl.rs index c1a2648f4dd..82a736933a0 100644 --- a/massa-execution-worker/src/interface_impl.rs +++ b/massa-execution-worker/src/interface_impl.rs @@ -130,6 +130,7 @@ impl InterfaceImpl { hd_cache_size: config.hd_cache_size, snip_amount: config.snip_amount, max_module_length: config.max_bytecode_size, + max_runtime_module_exports: config.max_runtime_module_exports, }))); // create an empty default store diff --git a/massa-models/src/config/constants.rs b/massa-models/src/config/constants.rs index f3469713880..9be834c8ca0 100644 --- a/massa-models/src/config/constants.rs +++ b/massa-models/src/config/constants.rs @@ -201,6 +201,9 @@ pub const MAX_FUNCTION_NAME_LENGTH: u16 = u16::MAX; pub const MAX_PARAMETERS_SIZE: u32 = 10_000_000; /// Maximum length of `rng_seed` in thread cycle pub const MAX_RNG_SEED_LENGTH: u32 = PERIODS_PER_CYCLE.saturating_mul(THREAD_COUNT as u64) as u32; +/// Maximum number of exports for a smart contract module +pub const MAX_RUNTIME_MODULE_EXPORTS: u32 = 500; // TODO: Calibrate + // *********************** // Bootstrap constants // diff --git a/massa-module-cache/src/config.rs b/massa-module-cache/src/config.rs index 0d202e7d418..1764c133908 100644 --- a/massa-module-cache/src/config.rs +++ b/massa-module-cache/src/config.rs @@ -16,4 +16,6 @@ pub struct ModuleCacheConfig { pub snip_amount: usize, /// Maximum length of a module pub max_module_length: u64, + /// Maximum number of exports in a module + pub max_runtime_module_exports: usize, } diff --git a/massa-module-cache/src/controller.rs b/massa-module-cache/src/controller.rs index 1362970e1a6..e02b672f9c2 100644 --- a/massa-module-cache/src/controller.rs +++ b/massa-module-cache/src/controller.rs @@ -41,7 +41,12 @@ impl ModuleCache { /// Internal function to compile and build `ModuleInfo` fn compile_cached(&mut self, bytecode: &[u8], hash: Hash) -> ModuleInfo { - match RuntimeModule::new(bytecode, self.cfg.gas_costs.clone(), Compiler::CL) { + match RuntimeModule::new( + bytecode, + self.cfg.gas_costs.clone(), + Compiler::CL, + self.cfg.max_runtime_module_exports, + ) { Ok(module) => { debug!("compilation of module {} succeeded", hash); ModuleInfo::Module(module) @@ -57,7 +62,11 @@ impl ModuleCache { /// Save a new or an already existing module in the cache pub fn save_module(&mut self, bytecode: &[u8]) { let hash = Hash::compute_from(bytecode); - if let Some(hd_module_info) = self.hd_cache.get(hash, self.cfg.gas_costs.clone()) { + if let Some(hd_module_info) = self.hd_cache.get( + hash, + self.cfg.gas_costs.clone(), + self.cfg.max_runtime_module_exports, + ) { debug!("save_module: {} present in hd", hash); self.lru_cache.insert(hash, hd_module_info); } else if let Some(lru_module_info) = self.lru_cache.get(hash) { @@ -110,7 +119,11 @@ impl ModuleCache { if let Some(lru_module_info) = self.lru_cache.get(hash) { debug!("load_module: {} present in lru", hash); lru_module_info - } else if let Some(hd_module_info) = self.hd_cache.get(hash, self.cfg.gas_costs.clone()) { + } else if let Some(hd_module_info) = self.hd_cache.get( + hash, + self.cfg.gas_costs.clone(), + self.cfg.max_runtime_module_exports, + ) { debug!("load_module: {} missing in lru but present in hd", hash); self.lru_cache.insert(hash, hd_module_info.clone()); hd_module_info @@ -181,7 +194,12 @@ impl ModuleCache { "Provided gas {} is lower than the base instance creation gas cost {}", limit, self.cfg.gas_costs.max_instance_cost )))?; - let module = RuntimeModule::new(bytecode, self.cfg.gas_costs.clone(), Compiler::SP)?; + let module = RuntimeModule::new( + bytecode, + self.cfg.gas_costs.clone(), + Compiler::SP, + self.cfg.max_runtime_module_exports, + )?; Ok(module) } } diff --git a/massa-module-cache/src/hd_cache.rs b/massa-module-cache/src/hd_cache.rs index 5eb59cad25d..00bfc24b8d0 100644 --- a/massa-module-cache/src/hd_cache.rs +++ b/massa-module-cache/src/hd_cache.rs @@ -137,7 +137,7 @@ impl HDCache { } /// Retrieve a module - pub fn get(&self, hash: Hash, gas_costs: GasCosts) -> Option { + pub fn get(&self, hash: Hash, gas_costs: GasCosts, max_exports: usize) -> Option { let mut iterator = self .db .iterator(IteratorMode::From(&module_key!(hash), Direction::Forward)); @@ -153,9 +153,13 @@ impl HDCache { if let ModuleMetadata::Invalid(err_msg) = metadata { return Some(ModuleInfo::Invalid(err_msg)); } - let module = - RuntimeModule::deserialize(&ser_module, gas_costs.max_instance_cost, gas_costs) - .expect(MOD_DESER_ERROR); + let module = RuntimeModule::deserialize( + &ser_module, + gas_costs.max_instance_cost, + gas_costs, + max_exports, + ) + .expect(MOD_DESER_ERROR); let result = match metadata { ModuleMetadata::Invalid(err_msg) => ModuleInfo::Invalid(err_msg), ModuleMetadata::NotExecuted => ModuleInfo::Module(module), @@ -233,7 +237,7 @@ mod tests { 0x70, 0x30, ]; ModuleInfo::Module( - RuntimeModule::new(&bytecode, GasCosts::default(), Compiler::CL).unwrap(), + RuntimeModule::new(&bytecode, GasCosts::default(), Compiler::CL, 100).unwrap(), ) } @@ -253,16 +257,16 @@ mod tests { let gas_costs = GasCosts::default(); cache.insert(hash, module); - let cached_module_v1 = cache.get(hash, gas_costs.clone()).unwrap(); + let cached_module_v1 = cache.get(hash, gas_costs.clone(), 100).unwrap(); assert!(matches!(cached_module_v1, ModuleInfo::Module(_))); cache.set_init_cost(hash, init_cost); - let cached_module_v2 = cache.get(hash, gas_costs.clone()).unwrap(); + let cached_module_v2 = cache.get(hash, gas_costs.clone(), 100).unwrap(); assert!(matches!(cached_module_v2, ModuleInfo::ModuleAndDelta(_))); let err_msg = "test_error".to_string(); cache.set_invalid(hash, err_msg.clone()); - let cached_module_v3 = cache.get(hash, gas_costs).unwrap(); + let cached_module_v3 = cache.get(hash, gas_costs, 100).unwrap(); let ModuleInfo::Invalid(res_err) = cached_module_v3 else { panic!("expected ModuleInfo::Invalid"); }; @@ -309,7 +313,7 @@ mod tests { let mut rbytes = [0u8; 16]; thread_rng().fill_bytes(&mut rbytes); let get_key = Hash::compute_from(&rbytes); - let cached_module = cache.get(get_key, gas_costs.clone()); + let cached_module = cache.get(get_key, gas_costs.clone(), 100); assert!(cached_module.is_none()); } } diff --git a/massa-node/src/main.rs b/massa-node/src/main.rs index 1709fd5c684..3257b689184 100644 --- a/massa-node/src/main.rs +++ b/massa-node/src/main.rs @@ -518,6 +518,7 @@ async fn launch( .broadcast_slot_execution_traces_channel_capacity, max_execution_traces_slot_limit: SETTINGS.execution.execution_traces_limit, block_dump_folder_path, + max_runtime_module_exports: MAX_RUNTIME_MODULE_EXPORTS, }; let execution_channels = ExecutionChannels {