Skip to content

Commit bb7d6f7

Browse files
committed
feat: generate sp1 stdin for aggchain proof
1 parent c2785dd commit bb7d6f7

File tree

19 files changed

+946
-529
lines changed

19 files changed

+946
-529
lines changed

Cargo.lock

+394-318
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+2
Original file line numberDiff line numberDiff line change
@@ -98,3 +98,5 @@ sp1-core-machine = "=4.1.2"
9898
sp1-sdk = "=4.1.2"
9999
sp1-prover = "=4.1.2"
100100
sp1-zkvm = "=4.1.2"
101+
sp1-cc-client-executor = { git = "https://github.com/succinctlabs/sp1-contract-call/", rev = "c9bdace" }
102+
sp1-cc-host-executor = { git = "https://github.com/succinctlabs/sp1-contract-call/", rev = "c9bdace" }

crates/aggchain-proof-builder/Cargo.toml

+3
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ edition.workspace = true
55
license.workspace = true
66

77
[dependencies]
8+
alloy.workspace = true
9+
alloy-primitives.workspace = true
10+
811
futures.workspace = true
912
thiserror.workspace = true
1013
tower = { workspace = true, features = ["timeout"] }

crates/aggchain-proof-builder/src/error.rs

+5
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use crate::WitnessGeneration;
2+
13
#[derive(thiserror::Error, Debug)]
24
pub enum Error {
35
#[error("Failed to retrieve l2 chain data")]
@@ -11,4 +13,7 @@ pub enum Error {
1113

1214
#[error("Prover service returned the error: {0}")]
1315
ProverServiceError(String),
16+
17+
#[error("Prover witness generation error: {0}")]
18+
ProverWitnessGenerationError(#[source] WitnessGeneration)
1419
}

crates/aggchain-proof-builder/src/lib.rs

+144-12
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,23 @@ use std::sync::Arc;
55
use std::task::{Context, Poll};
66

77
use aggchain_proof_contracts::contracts::{
8-
L1RollupConfigHashFetcher, L2LocalExitRootFetcher, L2OutputAtBlockFetcher,
8+
L1RollupConfigHashFetcher, L2EVMStateSketchesFetched, L2LocalExitRootFetcher,
9+
L2OutputAtBlockFetcher,
910
};
1011
use aggchain_proof_contracts::AggchainContractsClient;
12+
use aggchain_proof_core::full_execution_proof::FepPublicValues;
13+
use aggchain_proof_core::local_exit_tree::hasher::Keccak256Hasher;
14+
use aggchain_proof_core::local_exit_tree::proof::LETMerkleProof;
1115
use aggchain_proof_core::proof::AggchainProofWitness;
16+
use aggchain_proof_core::{BridgeWitness, InsertedGER, L1InfoTreeLeaf};
1217
use aggchain_proof_types::{AggchainProofInputs, Digest};
18+
use alloy::eips::BlockNumberOrTag;
19+
use alloy_primitives::Address;
1320
pub use error::Error;
1421
use futures::{future::BoxFuture, FutureExt};
1522
use prover_executor::Executor;
16-
use sp1_sdk::{SP1Proof, SP1ProofWithPublicValues, SP1VerifyingKey};
23+
use sp1_sdk::network::B256;
24+
use sp1_sdk::{SP1Proof, SP1ProofWithPublicValues, SP1Stdin, SP1VerifyingKey};
1725
use tower::buffer::Buffer;
1826
use tower::util::BoxService;
1927
use tower::ServiceExt as _;
@@ -32,7 +40,7 @@ pub(crate) type ProverService = Buffer<
3240
/// All the data `aggchain-proof-builder` needs for the agghchain
3341
/// proof generation. Collected from various sources.
3442
pub struct AggchainProverInputs {
35-
pub proof_witness: AggchainProofWitness,
43+
pub sp1_stdin: SP1Stdin,
3644
pub start_block: u64,
3745
pub end_block: u64,
3846
}
@@ -78,6 +86,14 @@ pub struct AggchainProofBuilder<ContractsClient> {
7886
aggchain_proof_vkey: SP1VerifyingKey,
7987
}
8088

89+
#[derive(Debug, Clone, thiserror::Error)]
90+
pub enum WitnessGeneration {
91+
#[error("Invalid inserted GER.")]
92+
InvalidInsertedGer,
93+
#[error("Cannot interpret the aggregation proof as 'compressed' type.")]
94+
WrongAggregationProofType,
95+
}
96+
8197
impl<ContractsClient> AggchainProofBuilder<ContractsClient> {
8298
pub async fn new(
8399
config: &AggchainProofBuilderConfig,
@@ -107,37 +123,151 @@ impl<ContractsClient> AggchainProofBuilder<ContractsClient> {
107123
pub(crate) async fn retrieve_chain_data(
108124
contracts_client: Arc<ContractsClient>,
109125
request: AggchainProofBuilderRequest,
126+
origin_network: u32,
110127
) -> Result<AggchainProverInputs, Error>
111128
where
112-
ContractsClient:
113-
L2LocalExitRootFetcher + L2OutputAtBlockFetcher + L1RollupConfigHashFetcher,
129+
ContractsClient: L2LocalExitRootFetcher
130+
+ L2OutputAtBlockFetcher
131+
+ L2EVMStateSketchesFetched
132+
+ L1RollupConfigHashFetcher,
114133
{
115-
let _prev_local_exit_root = contracts_client
134+
// Fetch from RPCs
135+
let prev_local_exit_root = contracts_client
116136
.get_l2_local_exit_root(request.aggchain_proof_inputs.start_block - 1)
117137
.await
118138
.map_err(Error::L2ChainDataRetrievalError)?;
119139

120-
let _new_local_exit_root = contracts_client
140+
let new_local_exit_root = contracts_client
121141
.get_l2_local_exit_root(request.end_block)
122142
.await
123143
.map_err(Error::L2ChainDataRetrievalError)?;
124144

125-
let _l2_pre_root_output_at_block = contracts_client
145+
let l2_pre_root_output_at_block = contracts_client
126146
.get_l2_output_at_block(request.aggchain_proof_inputs.start_block - 1)
127147
.await
128148
.map_err(Error::L2ChainDataRetrievalError)?;
129149

130-
let _claim_root_output_at_block = contracts_client
150+
let claim_root_output_at_block = contracts_client
131151
.get_l2_output_at_block(request.end_block)
132152
.await
133153
.map_err(Error::L2ChainDataRetrievalError)?;
134154

135-
let _rollup_config_hash = contracts_client
155+
let rollup_config_hash = contracts_client
136156
.get_rollup_config_hash()
137157
.await
138158
.map_err(Error::L1ChainDataRetrievalError)?;
139159

140-
todo!()
160+
let sketches = contracts_client
161+
.get_evm_state_sketches(
162+
BlockNumberOrTag::Number(request.aggchain_proof_inputs.start_block),
163+
BlockNumberOrTag::Number(request.end_block),
164+
)
165+
.await
166+
.map_err(Error::L2ChainDataRetrievalError)?;
167+
168+
// From the request
169+
let inserted_gers: Vec<InsertedGER> = request
170+
.aggchain_proof_inputs
171+
.ger_leaves
172+
.values()
173+
.map(|claim_data| {
174+
Ok(InsertedGER {
175+
proof: claim_data.inclusion_proof.clone().try_into().map_err(|_| {
176+
Error::ProverWitnessGenerationError(WitnessGeneration::InvalidInsertedGer)
177+
})?,
178+
l1_info_tree_leaf: claim_data.l1_leaf.clone().into(),
179+
l1_info_tree_index: claim_data.l1_leaf.l1_info_tree_index,
180+
})
181+
})
182+
.collect::<Result<Vec<_>, _>>()?;
183+
184+
let inserted_gers_hash_chain = inserted_gers
185+
.iter()
186+
.map(|inserted_ger| inserted_ger.ger())
187+
.collect();
188+
189+
let global_indices: Vec<B256> = request
190+
.aggchain_proof_inputs
191+
.imported_bridge_exits
192+
.iter()
193+
.map(|ib| (&ib.global_index).into())
194+
.collect();
195+
196+
let l1_info_tree_leaf: (u32, L1InfoTreeLeaf) = (
197+
request
198+
.aggchain_proof_inputs
199+
.l1_info_tree_leaf
200+
.l1_info_tree_index,
201+
request.aggchain_proof_inputs.l1_info_tree_leaf.into(),
202+
);
203+
204+
// Considered empty for now
205+
let (removed_gers_hash_chain, global_indices_unset) = (vec![], vec![]);
206+
207+
let trusted_sequencer = Address::default(); // TODO: from config or l1
208+
209+
let fep = FepPublicValues {
210+
l1_head: l1_info_tree_leaf.1.block_hash,
211+
claim_block_num: request.end_block as u32,
212+
rollup_config_hash,
213+
prev_state_root: l2_pre_root_output_at_block.state_root,
214+
prev_withdrawal_storage_root: l2_pre_root_output_at_block.withdrawal_storage_root,
215+
prev_block_hash: l2_pre_root_output_at_block.latest_block_hash,
216+
new_state_root: claim_root_output_at_block.state_root,
217+
new_withdrawal_storage_root: claim_root_output_at_block.withdrawal_storage_root,
218+
new_block_hash: claim_root_output_at_block.latest_block_hash,
219+
trusted_sequencer,
220+
signature_optimistic_mode: None, // unsupported for now
221+
};
222+
223+
let prover_witness = AggchainProofWitness {
224+
prev_local_exit_root,
225+
new_local_exit_root,
226+
l1_info_root: request.aggchain_proof_inputs.l1_info_tree_root_hash,
227+
origin_network,
228+
fep,
229+
l1_info_tree_leaf,
230+
l1_head_inclusion_proof: LETMerkleProof::<Keccak256Hasher> {
231+
siblings: request
232+
.aggchain_proof_inputs
233+
.l1_info_tree_merkle_proof
234+
.clone(),
235+
},
236+
global_indices: global_indices.clone(),
237+
bridge_witness: BridgeWitness {
238+
inserted_gers,
239+
inserted_gers_hash_chain,
240+
removed_gers_hash_chain,
241+
global_indices_claimed: global_indices,
242+
global_indices_unset,
243+
inserted_ger_sketches: sketches.inserted_ger_sketches,
244+
removed_ger_sketches: sketches.removed_ger_sketches,
245+
claimed_global_index_sketches: sketches.claimed_global_index_sketches,
246+
unset_global_index_sketches: sketches.unset_global_index_sketches,
247+
bridge_address_sketch: sketches.bridge_address_sketch,
248+
new_ler_sketch: sketches.new_ler_sketch,
249+
},
250+
};
251+
252+
let SP1Proof::Compressed(aggregation_proof) = request.aggregation_proof.proof else {
253+
return Err(Error::ProverWitnessGenerationError(
254+
WitnessGeneration::WrongAggregationProofType,
255+
));
256+
};
257+
258+
let aggregation_vkey = aggregation_proof.vk.clone();
259+
let sp1_stdin = {
260+
let mut stdin = SP1Stdin::new();
261+
stdin.write(&prover_witness);
262+
stdin.write_proof(*aggregation_proof, aggregation_vkey);
263+
stdin
264+
};
265+
266+
Ok(AggchainProverInputs {
267+
start_block: request.aggchain_proof_inputs.start_block,
268+
end_block: request.end_block,
269+
sp1_stdin,
270+
})
141271
}
142272

143273
/// Generate aggchain proof
@@ -173,10 +303,12 @@ where
173303
fn call(&mut self, req: AggchainProofBuilderRequest) -> Self::Future {
174304
let contracts_client = self.contracts_client.clone();
175305
let prover = self.prover.clone();
306+
let origin_network = self.network_id;
176307
async move {
177308
// Retrieve all the necessary public inputs. Combine with
178309
// the data provided by the agg-sender in the request.
179-
let aggchain_prover_inputs = Self::retrieve_chain_data(contracts_client, req).await?;
310+
let aggchain_prover_inputs =
311+
Self::retrieve_chain_data(contracts_client, req, origin_network).await?;
180312

181313
// Generate aggchain proof.
182314
Self::generate_aggchain_proof(prover, aggchain_prover_inputs).await

crates/aggchain-proof-contracts/Cargo.toml

+4
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ prover-alloy.workspace = true
2121
prover-utils.workspace = true
2222
mockall = { workspace = true, optional = true }
2323

24+
# SP1 dependencies
25+
sp1-cc-client-executor.workspace = true
26+
sp1-cc-host-executor.workspace = true
27+
2428
[dev-dependencies]
2529
mockito.workspace = true
2630
test-log.workspace = true

crates/aggchain-proof-contracts/src/contracts.rs

+27-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
use aggchain_proof_types::Digest;
1+
use aggchain_proof_types::{Digest, HashChainSketches};
2+
use alloy::eips::BlockNumberOrTag;
23
use alloy::network::Ethereum;
34
use alloy::sol;
5+
use sp1_cc_client_executor::io::EVMStateSketch;
46

57
use crate::Error;
68

@@ -60,6 +62,15 @@ pub trait L1RollupConfigHashFetcher {
6062
async fn get_rollup_config_hash(&self) -> Result<Digest, Error>;
6163
}
6264

65+
#[async_trait::async_trait]
66+
pub trait L2EVMStateSketchesFetched {
67+
async fn get_evm_state_sketches(
68+
&self,
69+
start_block: BlockNumberOrTag,
70+
end_block: BlockNumberOrTag,
71+
) -> Result<AggchainStateSketches, Error>;
72+
}
73+
6374
/// L2 output at block data structure.
6475
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
6576
pub struct L2OutputAtBlock {
@@ -69,3 +80,18 @@ pub struct L2OutputAtBlock {
6980
pub latest_block_hash: Digest,
7081
pub output_root: Digest,
7182
}
83+
84+
pub struct AggchainStateSketches {
85+
/// State sketches to retrieve the inserted GER hash chain.
86+
pub inserted_ger_sketches: HashChainSketches,
87+
/// State sketches to retrieve the removed GER hash chain.
88+
pub removed_ger_sketches: HashChainSketches,
89+
/// State sketches to retrieve the claims hash chain.
90+
pub claimed_global_index_sketches: HashChainSketches,
91+
/// State sketches to retrieve the unset hash chain.
92+
pub unset_global_index_sketches: HashChainSketches,
93+
/// State sketch to retrieve the bridge address.
94+
pub bridge_address_sketch: EVMStateSketch,
95+
/// State sketch to retrieve the new LER.
96+
pub new_ler_sketch: EVMStateSketch,
97+
}

0 commit comments

Comments
 (0)