Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions c-api/libvmexeccapi.h
Original file line number Diff line number Diff line change
Expand Up @@ -1260,8 +1260,9 @@ enum vm_exec_result_t vm_exec_instance_memory_grow(struct vm_exec_instance_t *in
*
* C API function, works with raw object pointers.
*/
enum vm_exec_result_t vm_exec_set_opcode_costs(struct vm_exec_executor_t *executor_ptr,
const struct vm_exec_opcode_cost_t *opcode_cost_ptr);
enum vm_exec_result_t vm_exec_set_opcode_config(struct vm_exec_executor_t *executor_ptr,
int32_t opcode_vesion_code,
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parameter name has a typo: 'opcode_vesion_code' should be 'opcode_version_code'. This typo also affects the C header file.

Suggested change
int32_t opcode_vesion_code,
int32_t opcode_version_code,

Copilot uses AI. Check for mistakes.
const struct vm_exec_opcode_cost_t *opcode_cost_ptr);

/**
* Sets the number of points(gas) limit for the given instance.
Expand Down
24 changes: 20 additions & 4 deletions c-api/src/capi_metering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::capi_instance::{CapiInstance, vm_exec_instance_t};
use crate::service_singleton::with_service;
use crate::vm_exec_result_t;
use meta::capi_safe_unwind;
use multiversx_chain_vm_executor::OpcodeCost;
use multiversx_chain_vm_executor::{OpcodeConfig, OpcodeCost, OpcodeVersion};

#[allow(non_camel_case_types)]
#[repr(C)]
Expand All @@ -21,14 +21,30 @@ pub struct vm_exec_opcode_cost_t;
#[allow(clippy::cast_ptr_alignment)]
#[unsafe(no_mangle)]
#[capi_safe_unwind(vm_exec_result_t::VM_EXEC_ERROR)]
pub unsafe extern "C" fn vm_exec_set_opcode_costs(
pub unsafe extern "C" fn vm_exec_set_opcode_config(
executor_ptr: *mut vm_exec_executor_t,
opcode_vesion_code: i32,
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parameter name has a typo: 'opcode_vesion_code' should be 'opcode_version_code'.

Copilot uses AI. Check for mistakes.
opcode_cost_ptr: *const vm_exec_opcode_cost_t,
) -> vm_exec_result_t {
let capi_executor = cast_input_ptr!(executor_ptr, CapiExecutor, "executor ptr is null");
let opcode_costs: &OpcodeCost = unsafe { &*(opcode_cost_ptr as *const OpcodeCost) };

let result = capi_executor.content.set_opcode_cost(opcode_costs);
let Some(opcode_version) = OpcodeVersion::from_i32(opcode_vesion_code) else {
with_service(|service| {
service.update_last_error_str(format!(
"invalid opcode version code: {}",
opcode_vesion_code
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parameter name has a typo: 'opcode_vesion_code' should be 'opcode_version_code'. This is used in the error message formatting.

Copilot uses AI. Check for mistakes.
))
});
return vm_exec_result_t::VM_EXEC_ERROR;
};

let opcode_costs_ref: &OpcodeCost = unsafe { &*(opcode_cost_ptr as *const OpcodeCost) };
let opcode_config = OpcodeConfig {
opcode_version,
opcode_cost: opcode_costs_ref.clone(),
};

let result = capi_executor.content.set_opcode_config(opcode_config);
match result {
Ok(()) => vm_exec_result_t::VM_EXEC_OK,
Err(message) => {
Expand Down
4 changes: 2 additions & 2 deletions vm-executor-experimental/src/middlewares.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
mod we_breakpoints;
mod we_metering;
mod we_metering_helpers;
mod we_opcode_control;
mod we_opcode_cost;
mod we_opcode_trace;
mod we_protected_globals;
mod we_protected_globals_trait;

pub(crate) use we_breakpoints::*;
pub(crate) use we_metering::*;
pub use we_metering_helpers::*;
pub use we_opcode_control::OpcodeControl;
pub use we_opcode_cost::*;
pub use we_opcode_trace::OpcodeTracer;
pub use we_protected_globals::ProtectedGlobals;
pub use we_protected_globals_trait::MiddlewareWithProtectedGlobals;
19 changes: 9 additions & 10 deletions vm-executor-experimental/src/middlewares/we_metering.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
#![allow(unused)] // TODO: until we activate the local count mechanism

use super::{
BREAKPOINT_VALUE_OUT_OF_GAS, Breakpoints, MiddlewareWithProtectedGlobals, get_local_cost,
get_opcode_cost,
BREAKPOINT_VALUE_OUT_OF_GAS, Breakpoints, MiddlewareWithProtectedGlobals, get_opcode_cost,
};
use crate::we_helpers::{
create_global_index, get_global_value_u64, is_control_flow_operator, set_global_value_u64,
};
use multiversx_chain_vm_executor::{ExecutorError, OpcodeCost};
use multiversx_chain_vm_executor::{ExecutorError, OpcodeConfig, OpcodeCost};
use std::mem;
use std::sync::{Arc, Mutex};
use wasmer::sys::{FunctionMiddleware, MiddlewareReaderState, ModuleMiddleware};
Expand All @@ -29,20 +28,20 @@ struct MeteringGlobalIndexes {
#[derive(Debug)]
pub(crate) struct Metering {
unmetered_locals: usize,
opcode_cost: Arc<OpcodeCost>,
opcode_config: Arc<OpcodeConfig>,
breakpoints_middleware: Arc<Breakpoints>,
global_indexes: Mutex<Option<MeteringGlobalIndexes>>,
}

impl Metering {
pub(crate) fn new(
unmetered_locals: usize,
opcode_cost: Arc<OpcodeCost>,
opcode_config: Arc<OpcodeConfig>,
breakpoints_middleware: Arc<Breakpoints>,
) -> Self {
Self {
unmetered_locals,
opcode_cost,
opcode_config,
breakpoints_middleware,
global_indexes: Mutex::new(None),
}
Expand Down Expand Up @@ -78,7 +77,7 @@ impl ModuleMiddleware for Metering {
Box::new(FunctionMetering {
accumulated_cost: Default::default(),
unmetered_locals: self.unmetered_locals,
opcode_cost: self.opcode_cost.clone(),
opcode_config: self.opcode_config.clone(),
breakpoints_middleware: self.breakpoints_middleware.clone(),
global_indexes: self.global_indexes.lock().unwrap().clone().unwrap(),
})
Expand All @@ -104,7 +103,7 @@ impl ModuleMiddleware for Metering {
struct FunctionMetering {
accumulated_cost: u64,
unmetered_locals: usize,
opcode_cost: Arc<OpcodeCost>,
opcode_config: Arc<OpcodeConfig>,
breakpoints_middleware: Arc<Breakpoints>,
global_indexes: MeteringGlobalIndexes,
}
Expand Down Expand Up @@ -149,7 +148,7 @@ impl FunctionMiddleware for FunctionMetering {
// Get the cost of the current operator, and add it to the accumulator.
// This needs to be done before the metering logic, to prevent operators like `Call` from escaping metering in some
// corner cases.
let option = get_opcode_cost(&operator, &self.opcode_cost);
let option = get_opcode_cost(&operator, &self.opcode_config);
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The experimental executor's metering middleware does not include support for bulk memory operations (MemoryCopy and MemoryFill) that was added to the wasmer executor. This creates an inconsistency between the two implementations where bulk memory operations would not be properly metered in the experimental executor, even when using OpcodeVersion V2.

Suggested change
let option = get_opcode_cost(&operator, &self.opcode_config);
let option = match &operator {
// Explicit support for bulk memory operations to keep metering consistent
Operator::MemoryCopy { .. } => Some(self.opcode_config.opcode_memorycopy),
Operator::MemoryFill { .. } => Some(self.opcode_config.opcode_memoryfill),
_ => get_opcode_cost(&operator, &self.opcode_config),
};

Copilot uses AI. Check for mistakes.
match option {
Some(cost) => self.accumulated_cost += cost as u64,
None => {
Expand Down Expand Up @@ -182,7 +181,7 @@ impl FunctionMiddleware for FunctionMetering {
// let unmetered_locals = self.unmetered_locals as u32;
// if count > unmetered_locals {
// let metered_locals = count - unmetered_locals;
// let local_cost = get_local_cost(&self.opcode_cost.lock().unwrap());
// let local_cost = self.opcode_cost.lock().unwrap().opcode_localallocate;
// let metered_locals_cost = metered_locals * local_cost;
// self.accumulated_cost += metered_locals_cost as u64;
// }
Expand Down
145 changes: 0 additions & 145 deletions vm-executor-experimental/src/middlewares/we_metering_helpers.rs

This file was deleted.

Loading
Loading