|
| 1 | +# Moose |
| 2 | +Moose is a framework for secure multi-party computation, which offers an easy to use numpy-like Python API that allows users to build machine learning models that perform inference on encrypted data. |
| 3 | + |
| 4 | + |
| 5 | +### Threat model at Cape: honest, but curious |
| 6 | +It is permissible that if parties collude with each other, they can use result values to reconstruct inputs |
| 7 | +This threat model is less strict than active security, which takes into account that perhaps not every party follows given protocols |
| 8 | + |
| 9 | +### Moose has 3 (main) components: |
| 10 | +- EDSL (embedded domain specific language) - PyMoose |
| 11 | +- Elk compiler |
| 12 | +- Moose runtime |
| 13 | + |
| 14 | +### Running onnx with PyMoose |
| 15 | +Given an onnx file as input, a Moose computation is produced as follows: |
| 16 | +- Convert onnx to PyMoose predictor |
| 17 | +- PyMoose predictor builds an edsl computation using its `predictor_factory` method |
| 18 | +- edsl computation is traced by ASTTracer into a python Computation object |
| 19 | +- Python Computation serialized to msgpack; msgpack deserialized into Moose’s Computation struct |
| 20 | +- Dump Moose Computation to textual format; output the result |
| 21 | + |
| 22 | +### Interface between PyMoose and Moose |
| 23 | +- pymoose/pymoose/computation is the interface between PyMoose and Moose |
| 24 | +- pymoose/pymoose/computation/utils.py specifies how to serialize PyMoose computations (Python) to msgpack |
| 25 | +- moose/src/computations.rs deserializes msgpack to Moose computations, matching Python operators, values, and types with Rust analogues |
| 26 | +A computation is represented as a graph, where nodes = operators and edges = Values. Each edge has a Rust type and a Moose type |
| 27 | + |
| 28 | +### Levels of computations/Lowering |
| 29 | +- Lowering is implemented via multiple dispatch of “kernel” functions |
| 30 | +- Logical level (Python edsl) = top level |
| 31 | +- Lower from top level through intermediate representations (IR) levels to reach the bottom level (like traversing a tree in depth first search manner) |
| 32 | +- The final level is the runtime kernel, which is a (usually pure) Rust function/closure that can be executed at runtime |
| 33 | +- Each “level” is represented by a particular kernel; kernels are loosely organized into “dialects” (similar to Tensorflow MLIR) |
| 34 | + |
| 35 | + A level can, for example, relate to placement. |
| 36 | + Example: The logical level is higher than the “replicated” level, which defines replicated protocol implementations |
| 37 | + Example: The replicated level is higher than the “host” level, because replicated protocols consist of collections of host operations |
| 38 | + |
| 39 | + A level can also relate to different abstractions of values/types |
| 40 | + Example: Floatingpoint is an abstraction over Host/Mirrored implementations of floatingpoint ops. |
| 41 | + Example: HostFixedTensor is higher than HostRingTensor, because it consists of a HostRingTensor with additional metadata (integral/fractional precision) |
| 42 | + |
| 43 | +### Placements |
| 44 | +- Host = data is on just 1 machine |
| 45 | +- Mirrored = data is on several machines (the machines have the same data and perform the same operations to represent public data) |
| 46 | +- Replicated = data is secret shared across several machines |
| 47 | +- Additive = alternative secret sharing scheme, currently only used in subprotocols for replicated placement |
| 48 | + |
| 49 | +### Truncation |
| 50 | +Numbers are represented using fixed point representation: 128 bits for integer and fractional part. |
| 51 | +Results of operations on fixed point numbers must be truncated in some cases (e.g.: multiplication) to ensure that the result has the same number integer and fractional bits as the inputs. I.e.: fixed point representation must match for inputs and outputs. |
| 52 | + |
| 53 | +### Sessions |
| 54 | +There are 3 types of Sessions based on execution patterns: |
| 55 | +- Asynchronous (“prod”) |
| 56 | + Performs lowering until a runtime kernel is reached, then schedule a Tokio task |
| 57 | +- Synchronous (“dev”) |
| 58 | +- Symbolic (“graph analysis and optimization”) |
| 59 | + One can leverage symbolic execution to lower a computation without actually executing it (i.e.: run the computation with symbolic values instead of concrete values for its args). Depth-first lowering stops when a runtime kernel is reached; return computation graph after full graph has been lowered. |
| 60 | + |
| 61 | +### SymbolicStrategy |
| 62 | +More flexible API for symbolic execution. Allows the user to drop out of the usual lowering process used by the Sync/Async Session structs, e.g. to enforce graph-wide properties or make edits to the graph before continuing lowering |
| 63 | +API is currently incomplete/undefined, but will be designed to be convenient to write compile-time optimizations in the future |
| 64 | + |
| 65 | +### Runtime session attributes |
| 66 | +Role = host placement |
| 67 | +Identity = the host assigned to the role (e.g.: a string (Alice), IP address with a port) |
0 commit comments