Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Orchestrator, Executor and Executor Spawners #3

Merged
merged 32 commits into from
Dec 11, 2023
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
db2d841
feat: initial orchestrator struct with simple test code
sifnoc Nov 22, 2023
280a8fd
feat: orchestrator, executor and executor spawner
sifnoc Nov 23, 2023
c6ddf89
feat: added basic test cases
sifnoc Nov 24, 2023
5cdb550
chore: remove unused csv files
sifnoc Nov 24, 2023
bf04d99
fix: use default csv file on test
sifnoc Nov 24, 2023
ca23759
fix: test cases
sifnoc Nov 24, 2023
4d1fee7
feat: error handling with cancellation
sifnoc Nov 25, 2023
3e39b10
feat: created mock spawner and added more test cases
sifnoc Nov 27, 2023
089c744
chore: cancel when occur error
sifnoc Nov 27, 2023
b1ffced
chore: Update README
sifnoc Nov 28, 2023
f13aa9f
chore: renamed spanwers and small updates on README
sifnoc Nov 28, 2023
24e7c7e
fix: warnings; Update README
sifnoc Nov 29, 2023
74e0a50
chore: update README with diagram
sifnoc Nov 29, 2023
34e4f07
fix: refactor; updated README
sifnoc Nov 30, 2023
8634a91
fix: assign unused port on mock server
sifnoc Nov 30, 2023
fc17fc7
feat: finish cloud spawner
sifnoc Dec 1, 2023
a049680
feat: added test case for CloudSpawner; Update README
sifnoc Dec 1, 2023
1186202
feat: added aggregation example
sifnoc Dec 3, 2023
4a4d71b
fix: clippy; feature flag to use nightly in example
sifnoc Dec 4, 2023
f32fc8f
fix: applied latest v1 improvement
sifnoc Dec 4, 2023
27b5d4f
fix: example; README
sifnoc Dec 4, 2023
6b1a145
fix: retrieving preimage from sibling mini tree on AggregationMerkleS…
sifnoc Dec 5, 2023
d6dd01e
fix: example; updated README
sifnoc Dec 5, 2023
4b4e10e
fix: more error handling; added retry on executor
sifnoc Dec 6, 2023
f227c1f
chore: added description as in-line comments
sifnoc Dec 6, 2023
e61a1da
fix: update README for mini tree server; removed some part on main RE…
sifnoc Dec 7, 2023
c6ed945
chore: update README and added description as in-line
sifnoc Dec 7, 2023
726dbd7
fix: latest v1; minor changes on comments
sifnoc Dec 7, 2023
c8a2d7f
chore: update README; move csv folder to root
sifnoc Dec 7, 2023
679ed56
fix: return a ref of empty array on un-intended fn on AggregationMerk…
sifnoc Dec 7, 2023
b108d1b
fix: the container now using unused port on host
sifnoc Dec 8, 2023
be9b8f2
fix: applied latest v1-improvement; updated README; fixed minor
sifnoc Dec 8, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
/target
/src/data
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const_env = "0.1.2"
num-bigint = "0.4.4"
serde = { version = "1.0.192", features = ["derive"] }
serde_json = "1.0.108"
summa-backend = { git = "https://github.com/summa-dev/summa-solvency", branch = "v1-for-summa-aggregation", version = "0.1.0" }
summa-backend = { git = "https://github.com/summa-dev/summa-solvency", branch = "v1-improvements-and-consolidation" }
halo2_proofs = { git = "https://github.com/privacy-scaling-explorations/halo2", tag = "v2023_04_20"}
tokio = { version = "1.34.0", features = ["full"] }
reqwest = "0.11.22"
Expand Down
168 changes: 9 additions & 159 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,160 +1,10 @@
# Summa Aggregation

Summa Aggregation is a scalable solution specifically designed to accelerate the process of building Merkle sum tree.

Our benchmarks in Summa Solvency revealed that constructing a merkle sum tree is a major time-consuming aspect of proof generation.

The primary objective of Summa Aggregation is to enable efficient scaling in the construction of the tree by parallelization and distributed computation in multiple machines.

For further optimization in Summa Aggregation, we introduced the AggregationMerkleSumTree component. This component is designed for efficiently constructing large Merkle sum trees by utilizing smaller-sized Merkle sum tree.

## Diagram of Parallel Merkle Sum Tree Construction

The diagram illustrates a distributed approach to constructing the `AggregatedMerkleSumTree`, where an orchestrator delegates tasks to executors, which are then processed in parallel by workers. The following sections will explain the roles of the Orchestrator, Executor, Worker and ExecutorSpawner.

![diagram](/Orchestrator-diagram.png)

## Orchestrator

The Orchestrator in the Summa Aggregation serves as the central management component, coordinating the data processing activities. It plays a pivotal role in coordinating the activities of Executors and Workers, improving efficiency of tasks of building Merkle sum tree.
The final result of the Orchestrator is the construction of the `AggregationMerkleSumTree`. This is achieved by aggregating the mini-trees constructed by the Workers. The Worker in here refers to a container running `mini-tree-server`.

Key functions of the Orchestrator include:

- **Dynamic Executor Spawning**: The Orchestrator dynamically spawns Executors in numbers set by the user. Each Executor is then connected to a dedicated Worker for efficient task execution.

- **Task Management and Distribution**: It oversees the overall task flow, loading tasks and distributing them to Executors.

- **Error Management and Pipeline Control**: The Orchestrator handles basic pipeline control and responds to errors by initiating the cancellation of all tasks.

- **Build AggregationMerkleSumTree**: Its final result is that evaluate `AggregationMerkleSumTree` by aggregating the mini-trees generated by the Workers.

## Executor and Worker

The Executor acts as a crucial intermediary between the Orchestrator and Workers, facilitating the data processing workflow. Spawned by the Orchestrator, each Executor operates in a one-to-one relationship with a Worker. Its primary function is to generate a segment of the AggregationMerkleSumTree, known as a `mini-tree`, by processing entry data. These mini-trees are then aggregated by the Orchestrator to form the complete AggregationMerkleSumTree.

Key aspects of the Executor's role include:

- **Spawning and Connection**: Executors are dynamically spawned by the Orchestrator as part of the system's scalability. Each Executor is designed to connect with a Worker for task execution.

- **Data Handling and Task Distribution**: A primary function of the Executor is to receive data entries, often parsed and prepared by the Orchestrator. Upon receiving these entries, the Executor is responsible for forwarding them to its connected Worker.

- **Communication Bridge**: The Executor serves as a communication bridge within the data pipeline. It relays processed data, `mini-tree`, from Workers back to the Orchestrator.

## ExecutorSpawner

The `ExecutorSpawner` is responsible for initializing and terminating Executors. It can serve as the management point for creating `Executor` instances and Workers. The latter function as the `mini-tree-server`.

In the Summa-Aggregation, there are three types of `ExecutorSpawner` provided:

- **MockSpawner**: Primarily used for testing, this spawner initializes Executors suitable for various test scenarios, including negative test cases. The Worker spawned by this spawner runs a `mini-tree-server` locally.

- **LocalSpawner**: It is close to actual use cases, this spawner enables users to initialize Executors and Workers in local Docker environments.

- **CloudSpawner**: Ideal for scenarios where cloud resources are accessed. This spawner functions similarly to the `LocalSpawner`, but it initializes workers on remote machines. In particular, it can be run on a Swarm network using the `docker-compose` file, which is a specific configuration for the Swarm network. Additionally, it can run using existing worker node URLs if the configuration file is not set.

The Docker Swarm transforms multiple Docker hosts into a single virtual host, providing crucial capabilities for high availability and scalability. For more details about Docker Swarm mode, refer to the [official documentation](https://docs.docker.com/engine/swarm/).

While both `LocalSpawner` and `CloudSpawner` manage Docker containers, they differ in operational context. `LocalSpawner` handles individual containers directly, providing simplicity but limited scalability. In contrast, `CloudSpawner` may employs Docker Swarm to manage containers as services, thereby offering enhanced scalability and resilience, crucial for larger workloads.

It's important to note, however, that managing workers through these three type of `ExecutorSpawner`, is not mandatory. Technically, the `ExecutorSpawner` is a trait with minimal requirements for the Orchestrator, specifically the methods `spawn_executor` and `terminate_executor`. You can create your own spawner and use it with the Orchestrator.

## Orchestrating on Swarm

For Summa-Aggregation purposes, you need to prepare a distributed environment where Workers can run on remote machines (referred to as 'Nodes'). An example of this is using Swarm, as mentioned in the previous section. This section will introduce how to set up Swarm mode and test it using Docker CLI.

### Preparing Docker Swarm Mode

In Summa-Aggregation, the `CloudSpawner` is designed to operate on Docker Swarm. It requires the URLs of Workers for initiation, which are the IP addresses of the Workers joining the Swarm network as per the instructions below.

You can initialize your Docker environment in Swarm mode, which is essential for managing a cluster of Docker nodes as a single virtual system.

Note that setting up Swarm mode may not work well depending on the OS, as network configurations differ across operating systems.

1. **Activate Swarm Mode on the Main Machine**:

Run the following command to initialize Swarm mode:

```bash
Main $ docker swarm init
```

This command will output information about the Swarm, including a join token.

2. **Join Node to the Swarm**:

Use the join token provided by the main machine to add nodes to the swarm. On each node, run like:

```bash
Worker_1 $ docker swarm join --token <YOUR_JOIN_TOKEN> <MAIN_MACHINE_IP>:2377
```

Replace `<YOUR_JOIN_TOKEN>` with the actual token and `<MAIN_MACHINE_IP>` with the IP address of your main machine.

3. **Check Node Status**:

To confirm that the nodes are successfully joined to the swarm, check the node status on the main machine:

```bash
Main $ docker node ls
```

You should see a list of all nodes in the swarm, including their status, roles, and other details like this:

```bash
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
kby50cicvqd5d95o9pgt4puo9 * main Ready Active Leader 20.10.12
2adikgxr2l1zp9oqo4kowvw7n worker_1 Ready Active 20.10.12
dz2z2v7o06h6gazmjlspyr5c8 worker_2 Ready Active 20.10.12
````

You are ready to spawn more workers!

### Spawning More Workers with CloudSpawner

You can spawning or managing worker by `CloudSpawner` without using Docker CLI command, which will explain in here. However, even with a well-configured swarm network in the previous section, workers may not be created properly in various reason.

In this section, you can verify that you can create a 'mini-tree-server' on any node. Before introducing the specific instructions, it's important to understand that in Docker Swarm mode, containers are managed as services rather than by individual names.

To spawn more workers, follow these steps:

1. Deploy the Stack:

First, deploy your stack using the `docker-compose.yml` file if you haven't already:

```bash
Main $ docker stack deploy -c docker-compose.yml summa_aggregation
```

2. Scale the Service:

Utilize the 'scale' sub-command within the Docker 'service' command to adjust the number of replicas (workers) for your mini-tree service.

'mini-tree' refers to the name of the service, which is configured in the 'docker-compose.yml' file. Think of the number of replicas as the number of workers.

For example, to scale up to 5 workers, run:

```bash
Main $ docker service scale summa_aggregation_mini-tree=5
```

Since each worker has access to all of the node's resources, it would be appropriate to set the scale number based on the number of node.

3. Verify the Scaling:

Check that the service has been scaled properly with:

```bash
Main $ docker service ls
```

This command shows the number of replicas running for each service in the swarm.

Scaling service allows you to adjust the number of workers more easily than spawning each worker individually.
Summa Aggregation is a scalable solution specifically designed to accelerate the process of building Merkle sum tree. It addresses the time-intensive challenge of constructing these trees by enabling efficient scaling through parallelization and distributed computation across multiple machines.

## Running test

You can run the tests using following command:
Tests can be run using the following command:

```bash
cargo test --release
Expand All @@ -165,9 +15,8 @@ Please ensure that this port is not already in use to avoid errors.

## Running Additional Tests Involving Docker and Docker Swarm

To run additional tests involving Docker and Docker Swarm mode, ensure that your Docker registry contains the "summadev/summa-aggregation-mini-tree" image.
For additional tests involving Docker and Docker Swarm mode, the presence of the "summadev/summa-aggregation-mini-tree" image in the local Docker registry is required.

If you do not have this image, you can either build it or download it.

### Building the docker image

Expand All @@ -179,31 +28,32 @@ docker build . -t summadev/summa-aggregation-mini-tree

### Downloading the Docker Image

Alternatively, you can download the image from Docker Hub using the following command:
Alternatively, the image can be downloaded from Docker Hub:

```bash
docker pull summadev/summa-aggregation-mini-tree
```

Ensure that the "summadev/summa-aggregation-mini-tree" image exists in your local Docker registry.

### Testing with LocalSpawner

The following command runs an additional test case using the LocalSpawner, which spawns worker containers in the local Docker environment. This extra test case involves running two containers during the testing process:


```bash
cargo test --features docker
sifnoc marked this conversation as resolved.
Show resolved Hide resolved
```

### Testing with CloudSpawner

If your Docker environment is successfully running in Swarm mode, you can run an additional test case that spawns workers on Swarm nodes using the `CloudSpawner`. Before running this test, please refer to the section "Spawning More Workers with CloudSpawner" to check your Docker Swarm setup.
For Summa-Aggregation, it's necessary to prepare a distributed environment where Workers can operate on remote machines, referred to as 'Nodes'. For guidance on setting up swarm nodes, please see [Getting Started with swarm mode](https://docs.docker.com/engine/swarm/swarm-tutorial)

When the Docker environment is running successfully in Swarm mode, an additional test case that spawns workers on Swarm nodes using the `CloudSpawner` can be run:

```bash
cargo test --features docker-swarm
```

Please ensure that your Docker Swarm has at least one node connected to the manager node. Also, verify that each worker node in the swarm has the "summadev/summa-aggregation-mini-tree" image in its Docker registry. If a node connected to the manager node does not have the image, it will not be able to spawn workers on that node.
It is critical to ensure that the Docker Swarm includes at least one node connected to the manager node. Additionally, each worker node in the swarm must have the "summadev/summa-aggregation-mini-tree" image in its Docker registry. Without this image on nodes connected to the manager node, spawning workers on that node is not possible.

## Summa Aggregation Example

Expand Down
23 changes: 16 additions & 7 deletions bin/README.md
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be nice to link to this mini-readme from the main readme so that anyone who's deploying the project can easily find it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Upated at e61a1da

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like it got deleted somehow

Original file line number Diff line number Diff line change
@@ -1,24 +1,32 @@
# Mini Tree Server

Mini tree server is wrapped
Mini Tree Server is an Axum-based server that encapsulates the functionality of the Mini Tree Generator.

### Test Mini Tree Server
## Test Mini Tree Server

You can manually test the `Mini Tree Server` with running container.
First, to start the Mini Tree Server, use the command:

First, Use the command below to start the Mini Tree Server container:
```bash
cargo run --release --bin mini-tree-server
```

Alternatively, if you have the summa-aggregation-mini-tree image locally, can run the server with this command:
sifnoc marked this conversation as resolved.
Show resolved Hide resolved

```bash
docker run -d -p 4000:4000 --name mini-tree-server summa-aggretaion/mini-tree
docker run -d -p 4000:4000 --name mini-tree-server-test summadev/summa-aggregation-mini-tree
```

Second, to send two entries to the `Mini Tree Server`, use this script:
For details on obtaining the summadev/summa-aggregation-mini-tree image, please refer to the [Building Image](../README.md#building-the-docker-image) and [Downloading Image](../README.md#downloading-the-docker-image) sections in the README.

Second, send two entries to the Mini Tree Server, execute the following script:

```bash
bash ./scripts/test_sending_entry.sh
```

Upon successful execution, you will receive a response similar to the following
Note: Execute this command from the project's root folder to ensure proper functioning of scripts.

Upon successful execution, you will receive a response similar to the following:
<details>
<summary>Click View Response</summary>

Expand Down Expand Up @@ -66,3 +74,4 @@ Upon successful execution, you will receive a response similar to the following
this JSON output is prettified for clarity

</details>

File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
6 changes: 3 additions & 3 deletions examples/aggregation_flow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ async fn main() -> Result<(), Box<dyn Error>> {
let orchestrator = Orchestrator::<N_CURRENCIES, N_BYTES>::new(
Box::new(spawner),
vec![
"./src/orchestrator/csv/entry_16_1.csv".to_string(),
"./src/orchestrator/csv/entry_16_2.csv".to_string(),
"csv/entry_16_1.csv".to_string(),
"csv/entry_16_2.csv".to_string(),
],
);

Expand All @@ -99,7 +99,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
//
// Here, we demonstrate generating the proof of inclusion for User 0.
let inclusion_proof_of_user0 = round.get_proof_of_inclusion(0).unwrap();
assert!(inclusion_proof_of_user0.get_public_inputs().len() > 0); // Check public input counts
assert!(!inclusion_proof_of_user0.get_public_inputs().is_empty()); // Check public input counts

println!("Generated User 0 proof of inclusion");
Ok(())
Expand Down
Loading