wiki:RustInTor

Version 13 (modified by chelseakomlo, 4 months ago) (diff)

--

Rust in Tor

What & why

We are currently investigating integrating Rust as a first-class language in Tor. We decided upon Rust due to the benefits of memory safety and the ability to directly integrate Rust and C. To read more about how and why this started, see our meeting notes from the 2017 meeting in Amsterdam.

https://lists.torproject.org/pipermail/tor-dev/2017-March/012088.html

Current status

We are working to get basic structures in place in order to easily build Tor with Rust and add more Rust modules. This includes deciding how we will do dependency management, linking Rust and C modules, and type translation across the Rust/C FFI boundary. We recently merged #22106 which we will use to test platform support across distributions.

Future steps

We are currently working on:

  1. Adding automated tooling for code quality tools. We have #22156 to track this work.
  2. Implementing existing submodules in Rust as a proof of concept. Two that are currently in progress are consdiff and protover.

Interested in helping out?

As said before, right now we are still testing platform support and integration across the Rust/C FFI. There are a lot of places where help would be useful.

Testing Distribution Support

(We will soon add these instructions in doc/HACKING as well)

To build Tor with Rust:

You will need to run the configure script with the --enable-rust flag to explicitly build with Rust. Additionally, you will need to specify where to fetch Rust dependencies, as we allow for either fetching dependencies from Cargo or specifying a local directory.

To specify a local directory:

RUST_DEPENDENCIES='path_to_dependencies_directory' ./configure --enable-rust

To fetch dependencies from Cargo:

./configure --enable-rust --enable-cargo-online-mode

Identifying good candidates to move to Rust

The places in the Tor codebase that are good candidates for porting to Rust are:

  1. loosely coupled to other Tor submodules,
  2. have high test coverage, and
  3. would benefit from being implemented in a memory safe language.

Help in either identifying places such as this, or working to improve existing areas of the C codebase by adding regression tests and simplifying dependencies, would be really helpful.

Furthermore, as submodules in C are implemented in Rust, this is a good opportunity to refactor, add more tests, and split modules into smaller areas of responsibility.

Coding Standards

1. Rust module structure

We follow the generic structure of Rust modules. However, we require a tests/ directory for module API tests (this allows us to run these tests in the entire Tor test suite).

2. Keep FFI and library logic separate

Your Rust module should expose APIs in Rust that produce the exact same behavior as what the module FFI exposes. FFI bindings for external consumers should exist only to wrap Rust functions and translate for Tor C submodules.

These can be kept in a ffi.rs file.

For example, in a hypothetical tor_addition Rust module:

In lib.rs:

pub fn get_sum(a: i32, b: i32) -> i32 {
  a + b
}

In ffi.rs:

#[no_mangle]
pub unsafe extern "C" fn tor_get_sum(a: c_int, b: c_int) -> c_int {
  get_sum(a, b)
} 

3. Rust FFI bindings in Tor should only be called by Tor C submodules

Related to above, Rust modules should call each other directly. Tor C submodules should be the only consumer of Rust FFI bindings in Tor.

4. Isolate Rust dependencies to C

If your Rust module needs to call functions defined in Tor C code, these should be handled similar to Rust FFI bindings for C, but in a separate extern.rs file.

5. Avoid external crate dependencies

In general, we use modules from only the Rust standard library whenever possible. We will review including external crates on a case-by-case basis.

6. Ensure thorough test coverage

Rust modules in Tor can be tested at three levels.

  1. Public API tests

These should be in a /tests directory inside each Rust module and test that module's public Rust API.

  1. Tests for private functions

For functions not publicly exposed, these can be tested in the same file as the source code, per Rust convention.

However, the number of private functions within a Rust module should be limited- consider creating another Rust module to help maintain the "single responsibility" guideline for modules.

  1. Regression and integration tests

Your Rust module should be tested for regressions against existing Tor unit and integration tests. This should be done as part of the general Tor code submission process.

6. Ensure small module size

Modules should strive to be below 500 lines (tests excluded). Single responsibility and limited dependencies should be a guiding standard.

Getting Started

Please see our guide on getting started in writing part of Tor in Rust.

More to come

We are in the beginning phases and will keep this page updated as progress is made.

Ideas for more things to add to this page:

  • How to add new modules
  • How to call rust from C and C from rust
  • Which crates do we use?
  • Do we have coding standards?
  • How to get started?
  • Where do we put the code?
  • Note that we aren't taking rust-only features now.