Wasm Builders 🧱

Cover image for Rust X Wasm Compiled with Enarx
Kirtee Prajapati
Kirtee Prajapati

Posted on • Updated on

Rust X Wasm Compiled with Enarx

Introduction

Rust is Machine Oriented High Order language, or mohol best regarded as an extremely fast, robust, performant, scalable, and powerful System Programming Language i.e. it gives you low-level access to system resources, used more for writing Systems software, such as Drivers, and compiler tools, low-level networking code, databases and so one to make the code of software more efficient. C, C++, Swift, and golang are some the similar languages.
Rather than the user-facing software programs like Web application programming, gaming Software that can be done with languages like Java, JavaScript, Python, C#,

Rust is a great package manager and an ecosystem of crates, without a runtime.

It doesn't have a garbage collector, but instead uses a unique feature called Ownership (a third way to manage memory) which makes rust memory safe without using a garbage collector.

A brief discussion over memory management.

  1. Garbage collector is a piece of code that caters you memory management it has certain

    • pros: Error-free as they follow standard method, Faster write time since we don't have to deal with memory allocations.
    • Cons: Automating memory management can be a con in itself sometimes as you lose the fine-grained control over memory because cleaning memory any time between makes slower and unpredictable runtime performance, and lastly garbage collector itself takes some space, including with program increases program size.
  2. Manual memory management: here we get the access to manage(allocate or deallocate) memory, thereby faster runtime since we can optimize things, and ultimately smaller program size. but it too has some cons as writing programs keeping memory management in mind complicates it, and can be error-prone sometimes.

  3. Ownership model: It caters the benefits of both methods.

    • Control over memory: supports manual memory management.
    • Erro free: It does compile-time checks.
    • Faster runtime
    • Smaller program size.

con:

  • fighting with the borrow checker: Rust has strict memory management rules, and returns compile-time errors on violating them.

More technically Ownership follows 3 rules:

  1. Each value in Rust has a variable that's called its owner
  2. There can only be one owner at a time.
  3. When the owner goes out of the scope, the values will be dropped

Programs we can Build with Rust.

  1. CLI(command-line interface) programs: without GUI they usually make up for functionality and flexibility.

  2. WebAssembly programs: Webassembly is a low-level assembly-like language in a binary format created for a stack-based virtual machine that all the major browsers have implemented nowadays. most importantly major programs written in C, C++, C#, python, Golang, Rust, and 40 others can be compiled down to .wasm and run alongside JavaScript in the browser. best for Computationally intensive tasks at near-native speeds like gamming, image manipulation, math, physics, audio effects, etc. for more you can read my blog: WebAssembly: New Capability to Web and check demos with many High-level languages in series: Wasm demos

  3. Server-side apps or Networking services: Rust has a mature ecosystem to write backends like the native driver for MongoDB, SQLite, Postgres, MySQL, and support for logging, authorization, templating, and email. but it still doesn't have a dominant framework analogous to rails or Django

  4. Embedded programs: Devices made for some specialized purpose
    Enarx runs applications in TEE instances and aims to minimize the trust relationships required when executing applications. like Central heating systems, Electronic calculators, fitness watches, IoT devices, GPS.

One can also create Blockchain smart contracts(ex. Solana blockchain), Games, some GUI applications although the ecosystem is not fairly mature.

So we are done with understanding the bond of Wasm and Rust.

In this blog, I'll be posting about setting up Enarx as a backend and the procedure of implementing Enarx keeps over the Rust project.

Before we start let me mention that the Enarx uses this epic combination to make Confidential Computation Language and Architecture independent, it is hardware-specific framework threby OS dependent, i.e Linux is recommended if you are a Windows user or macOS.

It requires a CPU with a supported Trusted Execution Environment. and currently it supports **Intel SGX and AMD SEV-SNP"

I'm in Intel SGX support device so my focus will the same.

for Hardware requirements and for AMD SEV device support you can refer to Enarx Docs

Installing Enarx

1. Setting Up for SGX machine

  • Run a recent kernel with SGX support compiled in
  • Set the SGX device node permissions.
# groupadd -r sgx_prv
# cat > /etc/udev/rules.d/99-sgx.rules <<EOF

$ SUBSYSTEM=="misc", KERNEL=="sgx_provision", MODE="0660", GROUP="sgx_prv"
$ SUBSYSTEM=="misc", KERNEL=="sgx_enclave", MODE="0666"
Enter fullscreen mode Exit fullscreen mode

Since everyone cannot access hardware with the support for Intel SGX or AMD SEV-SNP, so Enarx facilitates you with KVM support that can be run on devices other than this which have virtualization support.

KVM (Kernel-based Virtual Machine) is a full virtualization solution for Linux on x86 hardware containing virtualization extensions (Intel VT or AMD-V).

KVM is loaded automatically by Linux Kernel.
you can check its presence by running the following command.

$ lsmod | grep kvm
Enter fullscreen mode Exit fullscreen mode

expected output should be
Image description

for amd intel would get replaced with it.

Now with this, you are done with Hardware requirements and certain permissions. Now it's time to set up your project, before that,

2. Install Dependencies

Debian / Ubuntu

$ sudo apt update
$ sudo apt install git curl gcc pkg-config libssl-dev musl-tools python3-minimal
Enter fullscreen mode Exit fullscreen mode

3. Install Rust

$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y

# set path variable
$ source $HOME/.cargo/env
Enter fullscreen mode Exit fullscreen mode

4. Install Enarx

From Github

$ git clone https://github.com/enarx/enarx
$ cd enarx/
$ cargo build

$ cargo install --bin enarx --path ./
Enter fullscreen mode Exit fullscreen mode

you can also install with alternative methods like crates.io and Nix.

Since Enarx supports binary files for so to convert that we'll Build and run a WebAssembly module

5. Install WebAssembly Rust toolchain

$ rustup target install wasm32-wasi
$ cd~/
Enter fullscreen mode Exit fullscreen mode

so now Enarx is installed in your system and it's globally accessible
outside of the Enarx repository

Setting Up a New Rust program.

Hello World

$ cargo init --bin hello-world
$ cd hello-world
Enter fullscreen mode Exit fullscreen mode

cargo new generates a “Hello, world!” program by default. in src/main.rs file.

Assuming you did install the enarx binary and have it in your $PATH, you can now run the WebAssembly program in an Enarx keep.

$ enarx run target/wasm32-wasi/release/hello-world.wasm
Enter fullscreen mode Exit fullscreen mode

Image description

Guessing Game

$ cargo new guessing_game
$ cd guessing_game
Enter fullscreen mode Exit fullscreen mode

Look at the generated Cargo.toml file: and update the dependencies section.

[package]
name = "guessing_game"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
rand="0.3.14"
Enter fullscreen mode Exit fullscreen mode

Inside src/main.lib add:

use rand::Rng;
use std::cmp::Ordering;
use std::io;

fn main() {
    println!("Guess the number!");

    let secret_number = rand::thread_rng().gen_range(1..101);

    loop {
        println!("Please input your guess.");

        let mut guess = String::new();

        io::stdin()
            .read_line(&mut guess)
            .expect("Failed to read line");

        let guess: u32 = match guess.trim().parse() {
            Ok(num) => num,
            Err(_) => continue,
        };

        println!("You guessed: {}", guess);

        match guess.cmp(&secret_number) {
            Ordering::Less => println!("Too small!"),
            Ordering::Greater => println!("Too big!"),
            Ordering::Equal => {
                println!("You win!");
                break;
            }
        }
    }
}

Enter fullscreen mode Exit fullscreen mode

Similar to the above compilation:
Compile the guessing_game into .wasm.

$ cargo build --release --target=wasm32-wasi
Enter fullscreen mode Exit fullscreen mode

compile to Enarx Keep

$ enarx run target/wasm32-wasi/release/hello-world.wasm
Enter fullscreen mode Exit fullscreen mode

Image description

To see what backends are supported on your system, run:

$ entry info
Enter fullscreen mode Exit fullscreen mode

Image description

Here you can see that my device Backend: kvm is supported and on manual selection backend "sgx" is unsupported.
So am working with backend=kvm target

You got the same output and this is all made possible by setting WebAssembly as compile target. you can read more on it in my blog ENARX with WASM: Language and Architecture Independent.

References:

I follow the youtube channel Let's Get Rusty for Rust-related content.

Latest comments (2)

Collapse
 
anara profile image
Silvana

Great Kirtee, my first file using Rust was a guessing game too, is cool!

Collapse
 
kirteeprajapati profile image
Kirtee Prajapati

ikr 😄 actually I too liked Guessing game as first Rust program to work on, my next approach would be to run a project on ENARX and so will post it If i got succeded