feat: add architecture doc (#73)

* feat: add architecture doc

* fix: typos
This commit is contained in:
Eduard S. 2025-02-18 16:31:39 +01:00 committed by GitHub
parent 1b6e0c9395
commit 2d4d31dce9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 46 additions and 1 deletions

View file

@ -18,3 +18,6 @@
- [MainPOD](./mainpod.md)
- [MockPOD](./mockpod.md)
- [Examples](./examples.md)
# Architecture
- [Architecture](./architecture.md)

42
book/src/architecture.md Normal file
View file

@ -0,0 +1,42 @@
# Architecture
This document explains the architecture of the current implementation.
The main logic of the POD2 implementation is divided into three modules:
- frontend
- compiles user-friendly pod declarations into intermediate representations to be consumed by the backend
- internally connects to the backend to get pods built (signed / proved).
- presents pods to the user
- middleware
- defines the intermediate representation of Statements, Operations and interfaces of PODs
- Statements and Operations are strongly typed here
- Both frontend and backend use types defined in the middleware
- Does not import types from frontend nor backend
- backend
- takes a middleware POD request representation, signs/proves it and returns a generic POD object
If this was the Rust language compiler:
- frontend: takes a Rust code and compiles it to LLVM-IR
- middleware: defines LLVM-IR instructions and blocks
- backend: Takes LLVM-IR instructions and emits assembly code for a particular CPU
The following diagram shows visually how the components interact with each other:
![](img/frontend-backend.png)
In this organization, the middleware could be defined at arbitrary points:
- closer to the user would be more high level
- closer to the target would be more low level
All these positions are OK. We just need to choose one, and we can try to choose a point that simplifies the implementation.
For example in the middleware we could define `Value = 4 x Goldilock` (making it slightly low level); or `Value = BigUint` and letting the backend choose the maximum representable value, the field encoding, etc. (making it slightly higher level).
In the current iteration we choose `Value = 4 x Goldilock`, but we can revisit it in a future iteration (eg. if we want to support plonky3) by either moving the middleware to a higher level, or by keeping it the same and replacing the `Value` definition.
The diagram above includes an arrow that would show the typical flow followed by a user making a POD. This is a simplified description of the process.
1. The user interacts with the frontend API and passes a list of Operations. The frontend takes those operations and generates the corresponding Statements. The list of Operations and Statements are transformed into middleware types. This process can be seen as a compilation step. The frontend sends this middleware data as a request to the Backend.
2. The backend receives a request to build a POD from a list of Statements and Operations. It takes that bundle of data and lays it out in the appropriate format to be proved by a circuit, padding unused slots, etc. Then it calls a proof system API to generate a proof.
3. The target (proof system) generates a proof from some circuit description and witness data and gives it back to the backend.
4. The backend receives the proof and encapsulates it in an object that adheres to the Pod trait and passes it to the frontend
5. The frontend receives a "blackbox" Pod object and wraps it in a presentation layer in order to show it to the user.

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB