Implement Gas Metering for pre-instrumented modules. Closes
#include <ctype.h>
#include "wasm3.h"
+#include "m3_api_defs.h"
#include "m3_api_wasi.h"
#include "m3_api_libc.h"
#include "m3_api_tracer.h"
-#define FATAL(msg, ...) { printf("Error: [Fatal] " msg "\n", ##__VA_ARGS__); goto _onfatal; }
+// Gas metering/limit only applies to pre-instrumented modules
+#define GAS_LIMIT 2000000000000
+
+#define FATAL(msg, ...) { fprintf(stderr, "Error: [Fatal] " msg "\n", ##__VA_ARGS__); goto _onfatal; }
#if defined(d_m3HasWASI) || defined(d_m3HasMetaWASI) || defined(d_m3HasUVWASI)
#define LINK_WASI
IM3Environment env;
IM3Runtime runtime;
+#if defined(GAS_LIMIT)
+
+static int64_t current_gas = GAS_LIMIT;
+static bool is_gas_metered = false;
+
+m3ApiRawFunction(metering_usegas)
+{
+ m3ApiGetArg (int32_t, gas)
+
+ current_gas -= gas;
+
+ if (UNLIKELY(current_gas < 0)) {
+ m3ApiTrap("[trap] Out of gas");
+ }
+ m3ApiSuccess();
+}
+
+#endif // GAS_LIMIT
+
+
M3Result link_all (IM3Module module)
{
M3Result res;
@@ -43,6 +67,15 @@ M3Result link_all (IM3Module module)
if (res) return res;
#endif
+#if defined(GAS_LIMIT)
+ res = m3_LinkRawFunction (module, "metering", "usegas", "v(i)", &metering_usegas);
+ if (!res) {
+ fprintf(stderr, "Warning: Gas is limited to %0.4f\n", (double)(current_gas)/10000);
+ is_gas_metered = true;
+ }
+ if (res == m3Err_functionLookupFailed) { res = NULL; }
+#endif
+
return res;
}
@@ -199,6 +232,13 @@ M3Result repl_call (const char* name, int argc, const char* argv[])
}
result = m3_CallArgv (func, argc, argv);
+
+#if defined(GAS_LIMIT)
+ if (is_gas_metered) {
+ fprintf(stderr, "Gas used: %0.4f\n", (double)(GAS_LIMIT - current_gas)/10000);
+ }
+#endif
+
if (result) return result;
static uint64_t valbuff[128];
