diff --git a/.github/workflows/send-proofs-docker.yml b/.github/workflows/send-proofs-docker.yml index 84641479c1..c487d6fa44 100644 --- a/.github/workflows/send-proofs-docker.yml +++ b/.github/workflows/send-proofs-docker.yml @@ -46,6 +46,17 @@ jobs: - name: Verify all sent proofs run: make docker_verify_proof_submission_success + + - name: Aggregate sp1 proofs + run: make docker_proof_aggregator_run_sp1 + - name: Verify SP1 aggregation + run: make docker_proof_aggregator_verify + + - name: Aggregate risc0 proofs + run: make docker_proof_aggregator_run_risc0 + + - name: Verify Risc0 aggregation + run: make docker_proof_aggregator_verify - name: Stop containers continue-on-error: true diff --git a/Makefile b/Makefile index 5857b7fd14..29011546f8 100644 --- a/Makefile +++ b/Makefile @@ -987,6 +987,9 @@ docker_build_operator: docker_build_batcher: docker compose -f docker-compose.yaml --profile batcher build +docker_build_proof_aggregator: + docker compose -f docker-compose.yaml --profile proof-aggregator build + docker_restart_aggregator: docker compose -f docker-compose.yaml --profile aggregator down docker compose -f docker-compose.yaml --profile aggregator up -d --remove-orphans --force-recreate @@ -1007,6 +1010,7 @@ docker_build: docker compose -f docker-compose.yaml --profile operator build docker compose -f docker-compose.yaml --profile batcher build docker compose -f docker-compose.yaml --profile aggregator build + docker compose -f docker-compose.yaml --profile proof-aggregator build docker_up: docker compose -f docker-compose.yaml --profile base up -d --remove-orphans --force-recreate @@ -1021,10 +1025,12 @@ docker_up: docker compose -f docker-compose.yaml --profile operator up -d --remove-orphans --force-recreate docker compose -f docker-compose.yaml run --rm user-fund-payment-service-devnet docker compose -f docker-compose.yaml --profile batcher up -d --remove-orphans --force-recreate + docker compose -f docker-compose.yaml --profile proof-aggregator up -d --remove-orphans --force-recreate @echo "Up and running" docker_down: docker compose -f docker-compose.yaml --profile batcher down + docker compose -f docker-compose.yaml --profile proof-aggregator down docker compose -f docker-compose.yaml --profile operator down docker compose -f docker-compose.yaml --profile base down @echo "Everything down" @@ -1176,6 +1182,21 @@ docker_verify_proof_submission_success: echo "All proofs verified successfully!"; \ ' +docker_proof_aggregator_run_sp1: + docker exec $(shell docker ps | grep proof-aggregator | awk '{print $$1}') \ + sh -c 'AGGREGATOR=sp1 \ + /aligned_layer/proof_aggregator_cpu /aligned_layer/config-files/config-proof-aggregator-docker.yaml \ + && echo "{\"last_aggregated_block\":0}" > config-files/proof-aggregator.last_aggregated_block.json' + +docker_proof_aggregator_run_risc0: + docker exec $(shell docker ps | grep proof-aggregator | awk '{print $$1}') \ + sh -c 'AGGREGATOR=risc0 \ + /aligned_layer/proof_aggregator_cpu /aligned_layer/config-files/config-proof-aggregator-docker.yaml \ + && echo "{\"last_aggregated_block\":0}" > config-files/proof-aggregator.last_aggregated_block.json' + +docker_proof_aggregator_verify: + @(docker logs $$(docker ps | grep proof-aggregator | awk '{print $$1}') | grep -q "Error while aggregating and submitting proofs" && exit 1) || exit 0 + docker_attach_foundry: docker exec -ti $(shell docker ps | grep anvil | awk '{print $$1}') /bin/bash @@ -1191,6 +1212,9 @@ docker_attach_operator: docker_attach_batcher: docker exec -ti $(shell docker ps | grep batcher | awk '{print $$1}') /bin/bash +docker_attach_proof_aggregator: + docker exec -ti $(shell docker ps | grep proof-aggregator | awk '{print $$1}') /bin/bash + docker_logs_anvil: docker compose -f docker-compose.yaml logs anvil -f @@ -1203,6 +1227,9 @@ docker_logs_operator: docker_logs_batcher: docker compose -f docker-compose.yaml logs batcher -f +docker_logs_proof_aggregator: + docker compose -f docker-compose.yaml logs proof-aggregator -f + __TELEMETRY__: ## ____ # TODO maybe add a target to run both metrics and telemetry diff --git a/aggregation_mode/build.rs b/aggregation_mode/build.rs index cb6e6363b5..251a6d0206 100644 --- a/aggregation_mode/build.rs +++ b/aggregation_mode/build.rs @@ -3,6 +3,9 @@ use std::collections::HashMap; // Reference: https://docs.succinct.xyz/docs/sp1/writing-programs/compiling#advanced-build-options-1 fn main() { + // If we are in docker, we don't want to build the programs with docker + let in_docker = std::env::var("IN_DOCKER").is_ok(); + sp1_build::build_program_with_args("./aggregation_programs/sp1", { sp1_build::BuildArgs { output_directory: Some("./aggregation_programs/sp1/elf".to_string()), @@ -12,7 +15,7 @@ fn main() { ], // We use Docker to generate a reproducible ELF that will be identical across all platforms // (https://docs.succinct.xyz/docs/sp1/writing-programs/compiling#production-builds) - docker: true, + docker: !in_docker, ..Default::default() } }); @@ -21,10 +24,14 @@ fn main() { // regardless of the machine or local environment, will produce the same ImageID let docker_options = DockerOptionsBuilder::default().build().unwrap(); // Reference: https://github.com/risc0/risc0/blob/main/risc0/build/src/config.rs#L73-L90 - let guest_options = GuestOptionsBuilder::default() - .use_docker(docker_options) - .build() - .unwrap(); + let guest_options = if !in_docker { + GuestOptionsBuilder::default() + .use_docker(docker_options) + .build() + .unwrap() + } else { + GuestOptionsBuilder::default().build().unwrap() + }; risc0_build::embed_methods_with_options(HashMap::from([( "risc0_aggregation_program", diff --git a/config-files/config-proof-aggregator-docker.yaml b/config-files/config-proof-aggregator-docker.yaml new file mode 100644 index 0000000000..7dacb39aa7 --- /dev/null +++ b/config-files/config-proof-aggregator-docker.yaml @@ -0,0 +1,19 @@ +aligned_service_manager_address: "0x1613beB3B2C4f22Ee086B2b38C1476A3cE7f78E8" +proof_aggregation_service_address: "0xFD471836031dc5108809D173A067e8486B9047A3" +eth_rpc_url: "http://anvil:8545" +eth_ws_url: "ws://anvil:8545" +max_proofs_in_queue: 1000 +last_aggregated_block_filepath: /aligned_layer/config-files/proof-aggregator.last_aggregated_block.json +proofs_per_chunk: 512 # Amount of proofs to process per chunk +# This number comes from the blob data limit +# Since each blob has a capacity of (4096 * 32) = 131.072 bytes +# But to not surpass the field modulus we pad with a 0xo byte so we have (4096 * 31) = 126.976 bytes +# of usable data +# Since each proof commitments takes 32 bytes hash +# We can aggregate as much proofs as 126.976 / 32 = 3968 per blob +total_proofs_limit: 3968 + + +ecdsa: + private_key_store_path: "/aligned_layer/config-files/anvil.proof-aggregator.ecdsa.key.json" + private_key_store_password: "" diff --git a/docker-compose.yaml b/docker-compose.yaml index fb5ef41e70..94affc9a0a 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -117,6 +117,19 @@ services: dockerfile: docker/batcher.Dockerfile profiles: - batcher + + proof-aggregator: + image: ghcr.io/yetanotherco/aligned_layer/proof-aggregator:latest + build: + context: . + dockerfile: docker/proof-aggregator.Dockerfile + # Privileged so that it can run docker in docker (necessary for proving) + privileged: true + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - ~/.sp1/circuits/:/root/.sp1/circuits/ + profiles: + - proof-aggregator aligned_base: image: ghcr.io/yetanotherco/aligned_layer/aligned_base:latest diff --git a/docker/README.md b/docker/README.md index 4e7f3c3935..8125d8b0e5 100644 --- a/docker/README.md +++ b/docker/README.md @@ -92,6 +92,26 @@ And you can run this to attach to the anvil/foundry container and run `cast` wit make docker_attach_foundry ``` +## Aggregation + +To aggregate SP1 proofs: + +```shell +make docker_proof_aggregator_run_sp1 +``` + +For Risc0: + +```shell +make docker_proof_aggregator_run_risc0 +``` + +To verify that the proofs have been aggregated correctly: + +```shell +make docker_proof_aggregator_verify +``` + ## Logs You can watch logs for the components with the following commands: @@ -111,3 +131,7 @@ make docker_logs_operator ```shell make docker_logs_batcher ``` + +```shell +make docker_logs_proof_aggregator +``` diff --git a/docker/proof-aggregator.Dockerfile b/docker/proof-aggregator.Dockerfile new file mode 100644 index 0000000000..3d9d2433c2 --- /dev/null +++ b/docker/proof-aggregator.Dockerfile @@ -0,0 +1,50 @@ +FROM ghcr.io/yetanotherco/aligned_layer/aligned_base:latest AS base + +# Install SP1 toolchain +RUN curl -L https://sp1up.succinct.xyz | bash -s -- -y +ENV PATH="/root/.sp1/bin:${PATH}" +RUN sp1up + +# Install Risc0 toolchain +RUN curl -L https://risczero.com/install | bash +ENV PATH="/root/.risc0/bin:${PATH}" +RUN rzup install + +COPY crates /aligned_layer/crates/ +COPY aggregation_mode /aligned_layer/aggregation_mode/ +WORKDIR /aligned_layer + +RUN IN_DOCKER=true cargo build --manifest-path ./aggregation_mode/Cargo.toml --features prove --release --bin proof_aggregator_cpu +RUN cd aggregation_mode && IN_DOCKER=true ./scripts/build_programs.sh + +FROM debian:bookworm-slim AS final + +RUN apt update -y && apt install -y libssl-dev ca-certificates + +# Install required tools and set up Docker repository +# Installing docker is necessary for SP1 and Risc0 wrapping to snark +RUN apt-get update && apt-get install -y \ + ca-certificates \ + curl \ + gnupg \ + lsb-release && \ + install -m 0755 -d /etc/apt/keyrings && \ + curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc && \ + chmod a+r /etc/apt/keyrings/docker.asc && \ + echo \ + "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \ + $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \ + tee /etc/apt/sources.list.d/docker.list > /dev/null && \ + apt-get update + +# Note, we don't need to install docker-ce and containerd.io as we pass the docker engine socket via docker volume +RUN apt-get install docker-ce-cli docker-buildx-plugin docker-compose-plugin -y + +COPY --from=base /aligned_layer/aggregation_mode/target/release/proof_aggregator_cpu /aligned_layer/proof_aggregator_cpu +COPY config-files/config-proof-aggregator-docker.yaml /aligned_layer/config-files/ +COPY config-files/proof-aggregator.last_aggregated_block.json /aligned_layer/config-files/ +COPY config-files/anvil.proof-aggregator.ecdsa.key.json /aligned_layer/config-files/ + +# Leave it in the background as this container is used to exec the proof_aggregator binary +CMD ["sleep","infinity"] +