WebAssembly RunKit, also known as WARK, is a highly efficient tool designed to execute WebAssembly (w/ WASI) modules within a secure sandboxed environment. It can meticulously calculate and report the precise resource usage of the module, including instruction cost and memory utilization.
You can use WARK as a Command-Line Interface (CLI) tool or as a web service, depending on your needs.
If you have Docker installed, you can use the following command to run WARK:
# Run the web service
docker run -it --rm -p 33000:33000 jacoblincool/wark server
To install WARK using Cargo, use the following command:
cargo install wark
To run a WebAssembly module using the CLI, use the following command:
wark run [OPTIONS] <module>
You can customize the execution with the following options:
-m, --memory <memory> Define memory limit in MB [default: 512]
-c, --cost <cost> Set computational cost limit in instruction count [default: 1000000000]
-i, --input <input> Specify input file path for the program [default: stdin]
--stderr <file> Redirect program's stderr to a file
-n, --no-report Suppress the report of the program's resource usage
- You can use the
--input
option to specify the input file path for the program. If you want to use stdin as the input, use-
as the input file path. - The stdout of the module will be printed to the stdout of the CLI.
- The stderr of the module will not be printed to the stderr of the CLI. Instead, use the
--stderr
option to redirect it to a file. - Unless suppressed with the
--no-report
option, the resource usage of the module will be printed to the stderr of the CLI.
To start the WARK server, use the following command:
wark server
You can use the
PORT
environment variable to specify the port number. The default port number is33000
.
To run a WebAssembly module, send a POST
request with a JSON object in the body containing the following fields:
curl 'http://127.0.0.1:33000/run' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <JWT_TOKEN>' \
--data '{
"cost": 10000000,
"memory": 512,
"input": "I am stdin input",
"wasm": "<base64 encoded wasm module>"
}'
The server will respond with a JSON object containing the following fields:
{
"success": true,
"cost": 1234567,
"memory": 345,
"stdout": "I am stdout output",
"stderr": "I am stderr output",
"message": "I am message"
}
To run the program in judge mode, send a POST
request with a JSON object in the body containing the following fields:
curl --location 'http://127.0.0.1:33000/judge' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <JWT_TOKEN>' \
--data '{
"wasm": "<base64 encoded wasm module>",
"specs": [
{
"judger": "IOFast",
"input": "Jacob",
"output_hash": "128783a055c41c0a79ad7376e8e22587cdca53ed1f9c47c46d02a7768992b325",
"cost": 1000000000,
"memory": 1024
},
{
"judger": "IOFast",
"input": "WOJ",
"output_hash": "75787b1df461d0c48f0229a7769cbcc37c7d96d6613f825b77e76afdd1eb790a",
"cost": 1000000000,
"memory": 1024
},
{
"judger": "IOFast",
"input": "WASM OJ Wonderland",
"output_hash": "8f02d3283b88d16766cb287090bf59135c873e9175759b73f96ffe674440ff21",
"cost": 1000000000,
"memory": 1024
},
{
"judger": "IOFast",
"input_url": "https://link-to-input.file/input.txt",
"output_hash": "87c215c4afeaf7ff7684ef90fd44649b2051bc4c68cf58bdad402fa304487b8w",
"cost": 1000000000,
"memory": 1024
}
]
}'
The server will respond with a JSON object containing the following fields:
{
"results": [
{
"success": true,
"cost": 3776,
"memory": 1,
"message": null,
"exception": null
},
{
"success": true,
"cost": 3692,
"memory": 1,
"message": null,
"exception": null
},
{
"success": true,
"cost": 4421,
"memory": 1,
"message": null,
"exception": null
},
{
"success": false,
"cost": 5848,
"memory": 1,
"message": null,
"exception": {
"type": "Output",
"reason": "Output hash mismatch. Expected 87c215c4afeaf7ff7684ef90fd44649b2051bc4c68cf58bdad402fa304487b8w, got 87c215c4afeaf7ff7684ef90fd44649b2051bc4c68cf58bdad402fa304487b8c"
}
}
]
}
Currently, the server only supports the IOFast
judger, which is a simple judger that compares the trimmed output of the program with the output_hash
field. If the output of the program matches the output_hash
field, indicating that the program has passed the test case. Otherwise, an Output
exception will be returned.
Remote inputs will be cached in the
http-cache
directory, the TTL of each cache is respecting theCache-Control
header of the response.
You can find the cost of each instruction in the src/cost.rs.
If you see
Penalty Instruction [Instruction Name]
, it means that the specific instruction was not included in the cost table. Therefore, its cost defaults to 1000 points.
Feel free to contribute to this project by submitting pull requests or reporting issues. Your help is always welcomed and appreciated!