# WARK **W**eb**A**ssembly **R**un**K**it, 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. ## Table of Contents - [WARK](#wark) - [Table of Contents](#table-of-contents) - [Installation](#installation) - [Docker](#docker) - [Cargo](#cargo) - [Usage](#usage) - [CLI](#cli) - [Options](#options) - [IO](#io) - [Web Service](#web-service) - [Run](#run) - [Judge](#judge) - [Cost Table](#cost-table) ## Installation ### Docker If you have Docker installed, you can use the following command to run WARK: ```sh # Run the web service docker run -it --rm -p 33000:33000 jacoblincool/wark server ``` ### Cargo To install WARK using Cargo, use the following command: ```sh cargo install wark ``` ## Usage ### CLI To run a WebAssembly module using the CLI, use the following command: ```sh wark run [OPTIONS] ``` #### Options You can customize the execution with the following options: ```sh -m, --memory Define memory limit in MB [default: 512] -c, --cost Set computational cost limit in instruction count [default: 1000000000] -i, --input Specify input file path for the program [default: stdin] --stderr Redirect program's stderr to a file -n, --no-report Suppress the report of the program's resource usage ``` #### IO - 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. ### Web Service To start the WARK server, use the following command: ```sh wark server ``` > You can use the `PORT` environment variable to specify the port number. The default port number is `33000`. #### Run To run a WebAssembly module, send a `POST` request with a JSON object in the body containing the following fields: ```sh curl 'http://127.0.0.1:33000/run' \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer ' \ --data '{ "cost": 10000000, "memory": 512, "input": "I am stdin input", "wasm": "" }' ``` The server will respond with a JSON object containing the following fields: ```json { "success": true, "cost": 1234567, "memory": 345, "stdout": "I am stdout output", "stderr": "I am stderr output", "message": "I am message" } ``` #### Judge To run the program in judge mode, send a `POST` request with a JSON object in the body containing the following fields: ```sh curl --location 'http://127.0.0.1:33000/judge' \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer ' \ --data '{ "wasm": "", "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: ```json { "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 the `Cache-Control` header of the response. ## Cost Table You can find the cost of each instruction in the [src/cost.rs](./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!