Skip to content

Commit 91279ce

Browse files
committed
Merge remote-tracking branch 'origin/staging' into feat/integrate-agg-mode-with-db
2 parents 7a1e04c + 8019324 commit 91279ce

25 files changed

+517
-44
lines changed

.github/workflows/build-and-test-go.yml

Lines changed: 66 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ on:
1313
- "common/**"
1414
- "core/**"
1515
- "metrics/**"
16-
- ".github/workflows/build-go.yml"
16+
- ".github/workflows/build-and-test-go.yml"
1717
env:
1818
FFI_FOR_RELEASE: false
1919
jobs:
@@ -31,21 +31,83 @@ jobs:
3131
- name: foundry-toolchain
3232
uses: foundry-rs/[email protected]
3333

34+
- name: Cache SP1 bindings
35+
id: cache-sp1
36+
uses: actions/cache@v4
37+
with:
38+
path: operator/sp1/lib/libsp1_verifier_ffi.so
39+
key: sp1-bindings-${{ runner.os }}-${{ hashFiles('operator/sp1/lib/**/*.rs', 'operator/sp1/lib/Cargo.*') }}
40+
3441
- name: Build SP1 bindings
42+
if: steps.cache-sp1.outputs.cache-hit != 'true'
3543
run: make build_sp1_linux
3644

45+
- name: Clean SP1 build artifacts
46+
if: steps.cache-sp1.outputs.cache-hit != 'true'
47+
run: rm -rf operator/sp1/lib/target
48+
49+
- name: Cache Risc Zero bindings
50+
id: cache-risc-zero
51+
uses: actions/cache@v4
52+
with:
53+
path: operator/risc_zero/lib/librisc_zero_verifier_ffi.so
54+
key: risc-zero-bindings-${{ runner.os }}-${{ hashFiles('operator/risc_zero/lib/**/*.rs', 'operator/risc_zero/lib/Cargo.*') }}
55+
3756
- name: Build Risc Zero go bindings
57+
if: steps.cache-risc-zero.outputs.cache-hit != 'true'
3858
run: make build_risc_zero_linux
3959

60+
- name: Clean Risc Zero build artifacts
61+
if: steps.cache-risc-zero.outputs.cache-hit != 'true'
62+
run: rm -rf operator/risc_zero/lib/target
63+
64+
- name: Cache Merkle Tree bindings
65+
id: cache-merkle-tree
66+
uses: actions/cache@v4
67+
with:
68+
path: |
69+
operator/merkle_tree/lib/libmerkle_tree.so
70+
operator/merkle_tree/lib/libmerkle_tree.a
71+
key: merkle-tree-bindings-${{ runner.os }}-${{ hashFiles('operator/merkle_tree/lib/**/*.rs', 'operator/merkle_tree/lib/Cargo.*') }}
72+
4073
- name: Build Merkle Tree bindings
74+
if: steps.cache-merkle-tree.outputs.cache-hit != 'true'
4175
run: make build_merkle_tree_linux
42-
76+
77+
- name: Clean Merkle Tree build artifacts
78+
if: steps.cache-merkle-tree.outputs.cache-hit != 'true'
79+
run: rm -rf operator/merkle_tree/lib/target
80+
81+
- name: Cache Mina bindings
82+
id: cache-mina
83+
uses: actions/cache@v4
84+
with:
85+
path: operator/mina/lib/libmina_state_verifier_ffi.so
86+
key: mina-bindings-${{ runner.os }}-${{ hashFiles('operator/mina/lib/**/*.rs', 'operator/mina/lib/Cargo.*') }}
87+
4388
- name: Build Mina bindings
89+
if: steps.cache-mina.outputs.cache-hit != 'true'
4490
run: make build_mina_linux
45-
91+
92+
- name: Clean Mina build artifacts
93+
if: steps.cache-mina.outputs.cache-hit != 'true'
94+
run: rm -rf operator/mina/lib/target
95+
96+
- name: Cache Mina Account bindings
97+
id: cache-mina-account
98+
uses: actions/cache@v4
99+
with:
100+
path: operator/mina_account/lib/libmina_account_verifier_ffi.so
101+
key: mina-account-bindings-${{ runner.os }}-${{ hashFiles('operator/mina_account/lib/**/*.rs', 'operator/mina_account/lib/Cargo.*') }}
102+
46103
- name: Build Mina Account bindings
104+
if: steps.cache-mina-account.outputs.cache-hit != 'true'
47105
run: make build_mina_account_linux
48-
106+
107+
- name: Clean Mina Account build artifacts
108+
if: steps.cache-mina-account.outputs.cache-hit != 'true'
109+
run: rm -rf operator/mina_account/lib/target
110+
49111
- name: Build operator
50112
run: go build operator/cmd/main.go
51113

Makefile

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,9 @@ proof_aggregator_start_dev: is_aggregator_set reset_last_aggregated_block ./aggr
252252
proof_aggregator_start_dev_ethereum_package: is_aggregator_set reset_last_aggregated_block ./aggregation_mode/target/release/proof_aggregator_dev ## Starts proof aggregator with mock proofs (DEV mode) in ethereum package. Parameters: AGGREGATOR=<sp1|risc0>
253253
AGGREGATOR=$(AGGREGATOR) RISC0_DEV_MODE=1 ./aggregation_mode/target/release/proof_aggregator_dev config-files/config-proof-aggregator-mock-ethereum-package.yaml
254254

255+
proof_aggregator_test_without_compiling_agg_programs:
256+
cd aggregation_mode && SKIP_AGG_PROGRAMS_BUILD=1 cargo test -p proof_aggregator --tests -- --nocapture
257+
255258
### All CPU proof aggregator receipts
256259
./aggregation_mode/target/release/proof_aggregator_cpu: $(AGGREGATION_MODE_SOURCES)
257260
AGGREGATOR=$(AGGREGATOR) cargo build --features prove --manifest-path ./aggregation_mode/Cargo.toml --release --bin proof_aggregator_cpu
@@ -320,6 +323,22 @@ agg_mode_batcher_start_local: agg_mode_run_migrations
320323
agg_mode_batcher_start_ethereum_package: agg_mode_run_migrations
321324
cargo run --manifest-path ./aggregation_mode/Cargo.toml --release --bin agg_mode_batcher -- config-files/config-agg-mode-batcher-ethereum-package.yaml
322325

326+
AGG_MODE_SENDER ?= 0x70997970C51812dc3A010C7d01b50e0d17dc79C8
327+
agg_mode_batcher_send_payment:
328+
@cast send --value 1ether \
329+
0x922D6956C99E12DFeB3224DEA977D0939758A1Fe \
330+
--private-key 0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d
331+
332+
agg_mode_batcher_send_sp1_proof:
333+
@NONCE=$$(curl -s http://127.0.0.1:8089/nonce/0x70997970C51812dc3A010C7d01b50e0d17dc79C8 | jq -r '.data.nonce'); \
334+
curl -X POST \
335+
-H "Content-Type: multipart/form-data" \
336+
-F "nonce=$${NONCE}" \
337+
-F "proof=@scripts/test_files/sp1/sp1_fibonacci_5_0_0.proof" \
338+
-F "program_vk=@scripts/test_files/sp1/sp1_fibonacci_5_0_0_vk.bin" \
339+
-F "signature_hex=0x0" \
340+
http://127.0.0.1:8089/proof/sp1
341+
323342
__AGGREGATOR__: ## ____
324343

325344
aggregator_start: ## Start the Aggregator. Parameters: ENVIRONMENT=<devnet|testnet|mainnet>, AGG_CONFIG_FILE

aggregation_mode/Cargo.lock

Lines changed: 75 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

aggregation_mode/batcher/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,12 @@ serde = { workspace = true }
88
serde_json = { workspace = true }
99
serde_yaml = { workspace = true }
1010
aligned-sdk = { workspace = true }
11+
sp1-sdk = { workspace = true }
1112
tracing = { version = "0.1", features = ["log"] }
1213
tracing-subscriber = { version = "0.3.0", features = ["env-filter"] }
14+
bincode = "1.3.3"
1315
actix-web = "4"
16+
actix-multipart = "0.7.2"
1417
alloy = { workspace = true }
1518
tokio = { version = "1", features = ["time"]}
1619
# TODO: enable tls

aggregation_mode/batcher/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ pub mod config;
22
pub mod db;
33
pub mod payments;
44
pub mod server;
5+
mod verifiers;

aggregation_mode/batcher/src/server/http.rs

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@ use std::{
33
time::{SystemTime, UNIX_EPOCH},
44
};
55

6+
use actix_multipart::form::MultipartForm;
67
use actix_web::{
78
web::{self, Data},
89
App, HttpRequest, HttpResponse, HttpServer, Responder,
910
};
1011
use aligned_sdk::aggregation_layer::AggregationModeProvingSystem;
12+
use sp1_sdk::{SP1ProofWithPublicValues, SP1VerifyingKey};
1113
use sqlx::types::BigDecimal;
1214

1315
use super::{
@@ -18,9 +20,8 @@ use super::{
1820
use crate::{
1921
config::Config,
2022
db::Db,
21-
server::types::{
22-
SubmitProofRequest, SubmitProofRequestMessageRisc0, SubmitProofRequestMessageSP1,
23-
},
23+
server::types::{SubmitProofRequestRisc0, SubmitProofRequestSP1},
24+
verifiers::{verify_sp1_proof, VerificationError},
2425
};
2526

2627
#[derive(Clone, Debug)]
@@ -64,7 +65,6 @@ impl BatcherServer {
6465
};
6566

6667
// TODO: validate valid ethereum address
67-
6868
let Some(state) = req.app_data::<Data<BatcherServer>>() else {
6969
return HttpResponse::InternalServerError()
7070
.json(AppResponse::new_unsucessfull("Internal server error", 500));
@@ -84,11 +84,8 @@ impl BatcherServer {
8484

8585
async fn post_proof_sp1(
8686
req: HttpRequest,
87-
body: web::Json<SubmitProofRequest<SubmitProofRequestMessageSP1>>,
87+
MultipartForm(data): MultipartForm<SubmitProofRequestSP1>,
8888
) -> impl Responder {
89-
let data = body.into_inner();
90-
91-
// TODO: validate signature
9289
let recovered_address = "0x70997970C51812dc3A010C7d01b50e0d17dc79C8".to_lowercase();
9390

9491
let Some(state) = req.app_data::<Data<BatcherServer>>() else {
@@ -102,7 +99,7 @@ impl BatcherServer {
10299
.json(AppResponse::new_unsucessfull("Internal server error", 500));
103100
};
104101

105-
if data.nonce != (count as u64) {
102+
if data.nonce.0 != (count as u64) {
106103
return HttpResponse::BadRequest().json(AppResponse::new_unsucessfull(
107104
&format!("Invalid nonce, expected nonce = {count}"),
108105
400,
@@ -140,15 +137,42 @@ impl BatcherServer {
140137
));
141138
}
142139

143-
// TODO: decode proof and validate it
140+
let Ok(proof_content) = tokio::fs::read(data.proof.file.path()).await else {
141+
return HttpResponse::InternalServerError()
142+
.json(AppResponse::new_unsucessfull("Internal server error", 500));
143+
};
144+
145+
let Ok(proof) = bincode::deserialize::<SP1ProofWithPublicValues>(&proof_content) else {
146+
return HttpResponse::BadRequest()
147+
.json(AppResponse::new_unsucessfull("Invalid SP1 proof", 400));
148+
};
149+
150+
let Ok(vk_content) = tokio::fs::read(data.program_vk.file.path()).await else {
151+
return HttpResponse::InternalServerError()
152+
.json(AppResponse::new_unsucessfull("Internal server error", 500));
153+
};
154+
155+
let Ok(vk) = bincode::deserialize::<SP1VerifyingKey>(&vk_content) else {
156+
return HttpResponse::BadRequest()
157+
.json(AppResponse::new_unsucessfull("Invalid vk", 400));
158+
};
159+
160+
if let Err(e) = verify_sp1_proof(&proof, &vk) {
161+
let message = match e {
162+
VerificationError::InvalidProof => "Proof verification failed",
163+
VerificationError::UnsupportedProof => "Unsupported proof",
164+
};
165+
166+
return HttpResponse::BadRequest().json(AppResponse::new_unsucessfull(message, 400));
167+
};
144168

145169
match state
146170
.db
147171
.insert_task(
148172
&recovered_address,
149173
AggregationModeProvingSystem::SP1.as_u16() as i32,
150-
&data.message.proof,
151-
&data.message.program_vk_commitment,
174+
&proof_content,
175+
&vk_content,
152176
None,
153177
)
154178
.await
@@ -164,7 +188,7 @@ impl BatcherServer {
164188
/// TODO: complete for risc0 (see `post_proof_sp1`)
165189
async fn post_proof_risc0(
166190
_req: HttpRequest,
167-
_body: web::Json<SubmitProofRequest<SubmitProofRequestMessageRisc0>>,
191+
MultipartForm(_): MultipartForm<SubmitProofRequestRisc0>,
168192
) -> impl Responder {
169193
HttpResponse::Ok().json(AppResponse::new_sucessfull(serde_json::json!({})))
170194
}

0 commit comments

Comments
 (0)