Skip to content

Commit

Permalink
Design doc and update readme (#38)
Browse files Browse the repository at this point in the history
* design doc and update readme

* Minor improvements to "design and standards"

* update links

---------

Co-authored-by: Hendrik Eeckhaut <[email protected]>
  • Loading branch information
sinui0 and heeckhau authored Jul 27, 2023
1 parent 86f1687 commit a2007e6
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 21 deletions.
4 changes: 3 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ First off, thank you for contributing to `mpz`.
If your contribution is not straightforward, please first discuss the change you
wish to make by creating a new issue.

See [our design doc](./DESIGN.md) for information on design choices, standards and project structure.

## Reporting issues

Before reporting an issue on the
[issue tracker](https://github.com/tlsnotary/mpz/issues),
[issue tracker](https://github.com/privacy-scaling-explorations/mpz/issues),
please check that it has not already been reported by searching for some related
keywords.

Expand Down
88 changes: 88 additions & 0 deletions DESIGN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# Design and Standards 📃

## Support

### Compiler

All crates must support the latest Rust stable compiler version. mpz has a focus on usability, and alienating users who require stable support would be the opposite of that. Nightly features can be gated behind feature flags, but a stable configuration must always be available.

### Architecture

Crates should support the big build targets:
- `x86_64`
- `aarch64`
- `armv7`
- `wasm32-unknown-unknown`

## Dependencies

New dependencies should always receive consideration prior to adding them. Ask yourself:

- Is it maintained?
- Is it heavy, eg negatively affects build time?
- Does it employ good coding practices, eg no sloppy unsafe usage
- Architecture support?
- What alternatives are there?

### Reinventing the wheel

Avoid reinventing the wheel as much as possible. Every line of code written is a line of code that needs to be reviewed, tested, and maintained. Before implementing some functionality, search for well-adopted crates which already implement it. The bias should be towards code-reuse, even if you think you can squeeze out a 5% improvement over some other implementation. Open a PR for them instead.

This does not mean that we should avoid re-implementing something if we can achieve an order-of-magnitude greater performance in a way which is likely not to be accepted by another crate.

**RustCrypto**

mpz heavily utilizes crates provided by `RustCrypto`. Their implementations and traits should be preferred over re-implementing it ourselves. Eg. before implementing a primitive for the 1000th time, check if `RustCrypto` has it.

## Modularity 📦

### Crate structure

Avoid monolithic crates, and remember that a nest of feature flags is not modularity. The decision to split up a crate
is a matter of discretion, but generally crates should not include multiple different classes of functionality.

### Interfaces

mpz strives to provide clean abstractions and generic code, and this means good interfaces (traits). Before composing functionalities together by coupling concrete types, evaluate whether there is an existing trait instead, or introduce one otherwise.

### Core vs IO

A protocol which requires communication should be implemented such that the core functionality is independent of the IO. This approach has some upfront cost, but provides many benefits including better separation of concerns, cleaner and more comprehensive testing, and conduciveness to [strong typing](#message-types).

This is typically realized by separating code into two crates: `mycrate-core` and `mycrate`.

Also see the [async topic](#async-).

### Transport agnostic

Along with [our commitment to strong message typing](#message-types), our code must be *transport agnostic*. This means we do not couple our protocol implementations to any particular transport such as `TCP`. This ensures maximum flexibility for our users, makes testing easier, and naturally supports concurrency via multiplexing.

### Private-by-default

Related to modularity, focus should be on minimizing the surface area of an API. This means limiting the use of `pub` and `pub(crate)` as much as possible, except for intentional visibility as part of a coherent API.

## Typing 🛡️

### Message types

Messages communicated over the wire should be clearly defined, ie strongly typed. A protocol's implementation should not be coupled to concerns regarding serialization. Serde makes our lives easier for achieving this, while remaining agnostic of the _serialization format_. This also means that a low-level protocol implementation should never depend on the `Async(Write/Read)` traits, rather on the `Sink/Stream` traits provided by the `futures` crate.

### Type-states

The use of the [type state pattern](https://cliffle.com/blog/rust-typestate/) is strongly encouraged. The benefits of using type-states are numerous, particularly in crypto protocols, as it eliminates the potential for a variety of bugs caused by unexpected states or simply prevents misuse.

Often type-states can negatively affect code composability, as it can cause a combinatorial explosion of states. This can be alleviated by re-introducing polymorphism using enums. This does remove some of the benefits of type-states, however it preserves the underlying type safety of the _implementation_, ie an invalid state is still unrepresentable, but errors can occur at runtime.

## Async ☵

mpz heavily utilizes the asynchronous programming features provided by Rust. However, core crates should never contain asynchronous code, and this separation is quite natural due to [our other practices](#core-vs-io).

### Blocking code

"Long" blocking code should never be present within an async function, as that defeats the entire purpose. Instead, blocking code is delegated to a worker thread, typically using a `rayon` thread pool in combination with async memory-channels to make it awaitable.

Synchronous mutexes can still be used when it is certain they won't cause deadlocks, eg the lock is only ever held for a short duration and release does not depend on other concurrent branches.

### Executor Agnostic

All code in mpz should be *executor agnostic*. This means no coupling to a particular executor/runtime, eg `tokio`'s runtime. This may take some getting used to, but it ensures maximum compatibility for dependent projects. See [this blog post](https://blog.yoshuawuyts.com/tree-structured-concurrency/) on structured concurrency to better understand how to avoid the traps that the `Spawn` functionality poses, and how remaining executor agnostic avoids it entirely by only utilizing `Future` primitives.
58 changes: 38 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,39 @@
[![CI](https://github.com/tlsnotary/mpz/actions/workflows/rust.yml/badge.svg)](https://github.com/tlsnotary/mpz/actions)

<p align="center">
<img src="./tlsn-banner.png" width=1280 />
</p>
[![CI](https://github.com/privacy-scaling-explorations/mpz/actions/workflows/rust.yml/badge.svg)](https://github.com/privacy-scaling-explorations/mpz/actions)

# MPZ

Multi Party computation made eaZy in Rust
mpz is a collection of multi-party computation libraries written in Rust 🦀.

This project strives to provide safe, performant, modular and portable MPC software with a focus on usability.

MPC crates for the development of [TLSNotary](https://github.com/tlsnotary/tlsn)
See [our design doc](./DESIGN.md) for information on design choices, standards and project structure.

## ⚠️ Notice

This project is currently under active development and should not be used in production. Expect bugs and regular major breaking changes.
This project is currently under active development and should not be used in production. Expect bugs and regular major breaking changes. Use at your own risk.

## Crates

**Core**
- `mpz-core` - Assortment of low-level primitives.
- `matrix-transpose` - Bit-wise matrix transposition.
- `clmul` - Carry-less multiplication

**Circuits**
- `mpz-circuits` - Boolean circuit DSL
- `mpz-circuits-macros` - Proc-macros for `mpz-circuits`

**Oblivious Transfer**
- `mpz-ot` - High-level async APIs
- `mpz-ot-core` - Low-level types for OT, and core implementations of OT protocols.

**Garbled Circuits**
- `mpz-garble` - High-level APIs for boolean garbled circuit protocols, including VM abstractions.
- `mpz-garble-core` - Low-level types for boolean half-gate garbling algorithm.

**Share Conversion**
- `mpz-share-conversion` - High-level APIs for Multiplicative-to-Additive and Additive-to-Multiplicative share conversion protocols for a variety of fields.
- `mpz-share-conversion-core` - Low-level types for share conversion protocols.

## License
All crates in this repository are licensed under either of
Expand All @@ -22,22 +43,19 @@ All crates in this repository are licensed under either of

at your option.

## Overview

Home of multi-party computation libraries:

- oblivious transfer: Core building block used a lot in our codebase.
- garbling: We use several variants of garbled circuit executions in our codebase
(DEAP, Dual-Ex, ZK)
- circuits: code to build circuits, with some basic circuit components
available.
- share-conversion: supports converting between additive and multiplicative
shares for performing finite-field arithmetic in 2PC.

## Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
dual licensed as above, without any additional terms or conditions.

See [CONTRIBUTING.md](CONTRIBUTING.md).

## Contributors

- [TLSNotary](https://github.com/tlsnotary)


### Pronounciation

mpz is pronounced "em-peasy".

0 comments on commit a2007e6

Please sign in to comment.