Skip to content

Commit c9a833c

Browse files
committed
feat: generate sp1 stdin for aggchain proof
1 parent 4e807aa commit c9a833c

File tree

17 files changed

+704
-355
lines changed

17 files changed

+704
-355
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

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

143272
/// Generate aggchain proof
@@ -173,10 +302,12 @@ where
173302
fn call(&mut self, req: AggchainProofBuilderRequest) -> Self::Future {
174303
let contracts_client = self.contracts_client.clone();
175304
let prover = self.prover.clone();
305+
let origin_network = self.network_id;
176306
async move {
177307
// Retrieve all the necessary public inputs. Combine with
178308
// the data provided by the agg-sender in the request.
179-
let aggchain_prover_inputs = Self::retrieve_chain_data(contracts_client, req).await?;
309+
let aggchain_prover_inputs =
310+
Self::retrieve_chain_data(contracts_client, req, origin_network).await?;
180311

181312
// Generate aggchain proof.
182313
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

+15
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
use aggchain_proof_types::Digest;
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,19 @@ 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_prev_l2_block_sketch(
68+
&self,
69+
prev_l2_block: BlockNumberOrTag,
70+
) -> Result<EVMStateSketch, Error>;
71+
72+
async fn get_new_l2_block_sketch(
73+
&self,
74+
new_l2_block: BlockNumberOrTag,
75+
) -> Result<EVMStateSketch, Error>;
76+
}
77+
6378
/// L2 output at block data structure.
6479
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
6580
pub struct L2OutputAtBlock {

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

+56-2
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,20 @@ use std::str::FromStr;
99
use std::sync::Arc;
1010

1111
use aggchain_proof_types::Digest;
12-
use alloy::primitives::B256;
12+
use alloy::eips::BlockNumberOrTag;
13+
use alloy::network::AnyNetwork;
14+
use alloy::primitives::{Address, B256};
15+
use alloy::providers::RootProvider;
16+
use contracts::L2EVMStateSketchesFetched;
1317
use jsonrpsee::core::client::ClientT;
1418
use jsonrpsee::http_client::HttpClient;
1519
use jsonrpsee::rpc_params;
1620
use prover_alloy::{build_alloy_fill_provider, AlloyFillProvider};
21+
use sp1_cc_client_executor::io::EVMStateSketch;
22+
use sp1_cc_client_executor::ContractInput;
23+
use sp1_cc_host_executor::HostExecutor;
1724
use tracing::info;
25+
use url::Url;
1826

1927
use crate::config::AggchainProofContractsConfig;
2028
use crate::contracts::{
@@ -27,7 +35,10 @@ pub use crate::error::Error;
2735
/// `AggchainContractsClient` is a trait for interacting with the smart
2836
/// contracts relevant for the aggchain prover.
2937
pub trait AggchainContractsClient:
30-
L2LocalExitRootFetcher + L2OutputAtBlockFetcher + L1RollupConfigHashFetcher
38+
L2LocalExitRootFetcher
39+
+ L2OutputAtBlockFetcher
40+
+ L1RollupConfigHashFetcher
41+
+ L2EVMStateSketchesFetched
3142
{
3243
}
3344

@@ -41,6 +52,9 @@ pub struct AggchainContractsRpcClient<RpcProvider> {
4152
/// L2 rpc execution layer client.
4253
_l2_el_client: Arc<RpcProvider>,
4354

55+
/// L2 rpc execution layer client.
56+
l2_archive_endpoint: Url, // TODO: put directly RootProvider
57+
4458
/// L2 rpc consensus layer client (rollup node).
4559
l2_cl_client: Arc<HttpClient>,
4660

@@ -105,6 +119,45 @@ where
105119
}
106120
}
107121

122+
#[async_trait::async_trait]
123+
impl<RpcProvider> L2EVMStateSketchesFetched for AggchainContractsRpcClient<RpcProvider>
124+
where
125+
RpcProvider: alloy::providers::Provider + Send + Sync,
126+
{
127+
async fn get_prev_l2_block_sketch(
128+
&self,
129+
prev_l2_block: BlockNumberOrTag,
130+
) -> Result<EVMStateSketch, Error> {
131+
let root_provider = RootProvider::<AnyNetwork>::new_http(self.l2_archive_endpoint.clone());
132+
let mut executor: HostExecutor<RootProvider<AnyNetwork>> =
133+
HostExecutor::new(root_provider, prev_l2_block)
134+
.await
135+
.expect("d");
136+
137+
let _ = executor
138+
.execute(ContractInput::new_call(
139+
Address::default(), // should be ger
140+
Address::default(),
141+
GlobalExitRootManagerL2SovereignChain::bridgeAddressCall {},
142+
))
143+
.await
144+
.expect("todo");
145+
146+
//let bridge_address_sketch = executor.finalize().await.expect("todo");
147+
148+
let prev_l2_block_sketch: EVMStateSketch = todo!();
149+
150+
Ok(prev_l2_block_sketch)
151+
}
152+
153+
async fn get_new_l2_block_sketch(
154+
&self,
155+
_new_l2_block: BlockNumberOrTag,
156+
) -> Result<EVMStateSketch, Error> {
157+
todo!()
158+
}
159+
}
160+
108161
impl<RpcProvider> AggchainContractsRpcClient<RpcProvider> {
109162
fn parse_l2_output_root(json: serde_json::Value) -> Result<L2OutputAtBlock, Error> {
110163
fn parse_hash(json: &serde_json::Value, field: &str) -> Result<Digest, Error> {
@@ -204,6 +257,7 @@ impl AggchainContractsRpcClient<AlloyFillProvider> {
204257
l2_cl_client,
205258
polygon_zkevm_bridge_v2,
206259
aggchain_fep,
260+
l2_archive_endpoint: config.l2_execution_layer_rpc_endpoint.clone(),
207261
})
208262
}
209263
}

0 commit comments

Comments
 (0)