Skip to content

Commit

Permalink
feat: aggchain-proof-builder
Browse files Browse the repository at this point in the history
  • Loading branch information
atanmarko committed Feb 10, 2025
1 parent 054f012 commit a44d5b6
Show file tree
Hide file tree
Showing 29 changed files with 917 additions and 146 deletions.
484 changes: 450 additions & 34 deletions Cargo.lock

Large diffs are not rendered by default.

22 changes: 22 additions & 0 deletions crates/aggchain-proof-builder/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,32 @@ edition.workspace = true
license.workspace = true

[dependencies]
aggchain-proof-core.workspace = true
aggkit-prover-config.workspace = true
aggkit-prover-types.workspace = true
alloy = { version = '0.11.0', default-features = false, features = [
"consensus",
"reqwest",
"json-rpc",
"rlp",
"rpc",
"rpc-client",
"rpc-types-eth",
"rpc-types-trace",
"providers",
"transports",
"transport-http",
"rpc-types-debug",
] }

anyhow.workspace = true
futures.workspace = true
thiserror.workspace = true
tower = { workspace = true, features = ["timeout"] }
tracing.workspace = true
serde = { workspace = true, features = ["derive"] }
sp1-sdk = { workspace = true, features = ["native-gnark"] }
url = "2.5.4"

[lints]
workspace = true
121 changes: 111 additions & 10 deletions crates/aggchain-proof-builder/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,110 @@
mod provider;

use std::sync::Arc;
use std::task::{Context, Poll};

use aggchain_proof_core::proof::AggchainProofWitness;
use aggkit_prover_config::aggchain_proof_service::{
HTTP_RPC_NODE_BACKOFF_MAX_RETRIES, HTTP_RPC_NODE_INITIAL_BACKOFF_MS,
};
use aggkit_prover_config::AggchainProofBuilderConfig;
use aggkit_prover_types::AggchainProof;
use alloy::eips::{BlockId, BlockNumberOrTag};
use alloy::network::primitives::BlockTransactionsKind;
use alloy::primitives::B256;
use alloy::providers::Provider;
use alloy::transports::{RpcError, TransportErrorKind};
use futures::{future::BoxFuture, FutureExt};
use sp1_sdk::SP1ProofWithPublicValues;

use crate::provider::json_rpc::{build_http_retry_provider, AlloyProvider};

pub struct AgghcainProofBuilderRequest {
pub agg_span_proof: SP1ProofWithPublicValues,
// TODO add rest of the fields
}

pub struct Request {}
pub struct Response {}
#[derive(Clone, Debug)]
pub struct AgghcainProofBuilderResponse {
pub proof: AggchainProof,
}

#[derive(thiserror::Error, Debug)]
pub enum Error {
#[error("Noop")]
Noop,
#[error("Alloy error: {0}")]
AlloyProviderError(String),

#[error("Alloy transport rpc error: {0:?}")]
AlloyRpcTransportError(RpcError<TransportErrorKind>),

#[error("Proof generation error: {0:?}")]
ProofGenerationError(aggchain_proof_core::error::ProofError),
}

/// This service is responsible for building an Aggchain proof.
#[derive(Default, Clone)]
pub struct AggchainProofBuilderService {}
#[derive(Debug, Clone)]
pub struct AggchainProofBuilder {
l1_client: Arc<AlloyProvider>,
#[allow(unused)]
l2_client: Arc<AlloyProvider>,
}

impl AggchainProofBuilder {
pub fn new(config: &AggchainProofBuilderConfig) -> Result<Self, Error> {
Ok(AggchainProofBuilder {
l1_client: Arc::new(
build_http_retry_provider(
&config.l1_rpc_endpoint,
HTTP_RPC_NODE_INITIAL_BACKOFF_MS,
HTTP_RPC_NODE_BACKOFF_MAX_RETRIES,
)
.map_err(|e| Error::AlloyProviderError(e.to_string()))?,
),
l2_client: Arc::new(
build_http_retry_provider(
&config.l2_rpc_endpoint,
HTTP_RPC_NODE_INITIAL_BACKOFF_MS,
HTTP_RPC_NODE_BACKOFF_MAX_RETRIES,
)
.map_err(|e| Error::AlloyProviderError(e.to_string()))?,
),
})
}

pub async fn get_l1_block_hash(&self, block_num: u64) -> Result<B256, Error> {
let block = self
.l1_client
.get_block(
BlockId::Number(BlockNumberOrTag::Number(block_num)),
BlockTransactionsKind::Hashes,
)
.await
.map_err(Error::AlloyRpcTransportError)?
.ok_or(Error::AlloyProviderError(format!(
"target block {block_num} does not exist"
)))?;

impl tower::Service<Request> for AggchainProofBuilderService {
type Response = Response;
Ok(block.header.hash)
}

// Retrieve l1 and l2 public data needed for aggchain proof generation
pub async fn retrieve_chain_data(&self) -> Result<(), Error> {
//TODO decide output structure
todo!()
}

// Generate aggchain proof
pub async fn generate_aggchain_proof(
&self,
mut _aggchain_proof_witness: AggchainProofWitness,
) -> Result<AggchainProof, Error> {
//TODO implement
todo!()
}
}

impl tower::Service<AgghcainProofBuilderRequest> for AggchainProofBuilder {
type Response = AgghcainProofBuilderResponse;

type Error = Error;

Expand All @@ -26,7 +114,20 @@ impl tower::Service<Request> for AggchainProofBuilderService {
todo!()
}

fn call(&mut self, _req: Request) -> Self::Future {
async move { Ok(Response {}) }.boxed()
fn call(&mut self, _req: AgghcainProofBuilderRequest) -> Self::Future {
async move {
//TODO implement

// Call all necessary data retrieval
//self.retrieve_chain_data().await?;

// Generate proof
//self.generate_aggchain_proof().await?;

Ok(AgghcainProofBuilderResponse {
proof: Default::default(),
})
}
.boxed()
}
}
46 changes: 46 additions & 0 deletions crates/aggchain-proof-builder/src/provider/json_rpc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
use std::time::Duration;

use alloy::network::Ethereum;
use alloy::providers::fillers::{
BlobGasFiller, ChainIdFiller, FillProvider, GasFiller, JoinFill, NonceFiller,
};
use alloy::providers::Identity;
use alloy::transports::http::reqwest;
use alloy::transports::layers::RetryBackoffLayer;
use alloy::{
providers::{ProviderBuilder, RootProvider},
rpc::client::ClientBuilder,
};

const HTTP_CLIENT_CONNECTION_POOL_IDLE_TIMEOUT: u64 = 90;
const HTTP_CLIENT_MAX_IDLE_CONNECTIONS_PER_HOST: usize = 64;

pub type AlloyProvider = FillProvider<
JoinFill<
Identity,
JoinFill<GasFiller, JoinFill<BlobGasFiller, JoinFill<NonceFiller, ChainIdFiller>>>,
>,
RootProvider,
Ethereum,
>;

pub fn build_http_retry_provider(
rpc_url: &url::Url,
backoff: u64,
max_retries: u32,
) -> Result<AlloyProvider, anyhow::Error> {
let retry_policy = RetryBackoffLayer::new(max_retries, backoff, 5);
let reqwest_client = reqwest::ClientBuilder::new()
.pool_max_idle_per_host(HTTP_CLIENT_MAX_IDLE_CONNECTIONS_PER_HOST)
.pool_idle_timeout(Duration::from_secs(
HTTP_CLIENT_CONNECTION_POOL_IDLE_TIMEOUT,
))
.build()?;

let http = alloy::transports::http::Http::with_client(reqwest_client, rpc_url.clone());
let is_local = http.guess_local();
let client = ClientBuilder::default()
.layer(retry_policy)
.transport(http, is_local);
Ok(ProviderBuilder::new().on_client(client))
}
1 change: 1 addition & 0 deletions crates/aggchain-proof-builder/src/provider/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub(crate) mod json_rpc;
2 changes: 1 addition & 1 deletion crates/aggchain-proof-core/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
mod digest;
mod error;
pub mod error;
mod full_execution_proof;
pub mod proof;
2 changes: 1 addition & 1 deletion crates/aggchain-proof-core/src/proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ impl AggchainProofWitness {
}

/// Public values of the SP1 aggchain proof.
#[derive(Serialize, Deserialize)]
#[derive(Serialize, Deserialize, Default, Clone, Debug)]
pub struct AggchainProofPublicValues {
/// Previous local exit root.
pub prev_local_exit_root: Digest,
Expand Down
1 change: 1 addition & 0 deletions crates/aggkit-prover-config/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ humantime-serde = "1.1.1"
jsonrpsee.workspace = true
serde = { workspace = true, features = ["derive"] }
serde_with.workspace = true
sp1-sdk = { workspace = true, features = ["native-gnark"] }
thiserror.workspace = true
toml.workspace = true
tracing.workspace = true
Expand Down
37 changes: 37 additions & 0 deletions crates/aggkit-prover-config/src/aggchain_proof_builder.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
use std::str::FromStr;

use jsonrpsee::core::Serialize;
use serde::Deserialize;
use url::Url;

/// The Aggchain proof builder configuration
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(rename_all = "kebab-case")]
pub struct AggchainProofBuilderConfig {
/// Json rpc endpoint of the l1 node.
pub l1_rpc_endpoint: Url,

/// Json rpc endpoint of the l2 rollup node.
pub l2_rpc_endpoint: Url,

/// Id of the rollup chain
pub rollup_id: u32,
}

impl Default for AggchainProofBuilderConfig {
fn default() -> Self {
AggchainProofBuilderConfig {
l1_rpc_endpoint: default_l1_url(),
l2_rpc_endpoint: default_l2_url(),
rollup_id: 0,
}
}
}

fn default_l1_url() -> Url {
Url::from_str("127.0.0.1::8545").unwrap()
}

fn default_l2_url() -> Url {
Url::from_str("127.0.0.1::8546").unwrap()
}
20 changes: 20 additions & 0 deletions crates/aggkit-prover-config/src/aggchain_proof_service.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
use std::fmt::Debug;

use serde::{Deserialize, Serialize};

use crate::aggchain_proof_builder::AggchainProofBuilderConfig;
use crate::proposer_service::ProposerServiceConfig;

/// The initial blockchain node backoff in milliseconds
pub const HTTP_RPC_NODE_INITIAL_BACKOFF_MS: u64 = 5000;

/// The blockchain node backoff number of retries
pub const HTTP_RPC_NODE_BACKOFF_MAX_RETRIES: u32 = 64;

/// The Aggchain proof service configuration
#[derive(Serialize, Deserialize, Clone, Debug, Default)]
#[serde(rename_all = "kebab-case")]
pub struct AggchainProofServiceConfig {
pub aggchain_proof_builder_config: AggchainProofBuilderConfig,
pub proposer_service_config: ProposerServiceConfig,
}
19 changes: 15 additions & 4 deletions crates/aggkit-prover-config/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,25 @@ use std::path::Path;

use prover_config::{NetworkProverConfig, ProverType};
use prover_logger::log::Log;
use prover_utils::with;
use serde::{Deserialize, Serialize};

pub use crate::{shutdown::ShutdownConfig, telemetry::TelemetryConfig};
use crate::aggchain_proof_service::AggchainProofServiceConfig;
pub use crate::{
aggchain_proof_builder::AggchainProofBuilderConfig, shutdown::ShutdownConfig,
telemetry::TelemetryConfig,
};

pub mod aggchain_proof_service;

pub mod aggchain_proof_builder;
pub mod proposer_service;
pub mod shutdown;
pub(crate) mod telemetry;

pub(crate) const DEFAULT_IP: std::net::Ipv4Addr = std::net::Ipv4Addr::new(0, 0, 0, 0);

/// The Aggkit Prover configuration.
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "kebab-case")]
pub struct ProverConfig {
/// The gRPC endpoint used by the prover.
Expand All @@ -36,6 +43,9 @@ pub struct ProverConfig {
#[serde(default)]
pub shutdown: ShutdownConfig,

/// Aggchain proof service configuration
pub aggchain_proof_service: AggchainProofServiceConfig,

/// The primary prover to be used for generation of the pessimistic proof
#[serde(default)]
pub primary_prover: ProverType,
Expand All @@ -52,6 +62,7 @@ impl Default for ProverConfig {
log: Log::default(),
telemetry: TelemetryConfig::default(),
shutdown: ShutdownConfig::default(),
aggchain_proof_service: AggchainProofServiceConfig::default(),
primary_prover: ProverType::NetworkProver(NetworkProverConfig::default()),
fallback_prover: None,
grpc: Default::default(),
Expand All @@ -74,7 +85,7 @@ impl ProverConfig {
}
}

#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
#[serde(rename_all = "kebab-case")]
pub struct GrpcConfig {
#[serde(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone, Default)]
#[serde(rename_all = "kebab-case")]
pub struct ProposerServiceConfig {
pub client: ProposerClientConfig,
}

use std::str::FromStr;
use std::time::Duration;

use prover_utils::from_env_or_default;
use serde::{Deserialize, Serialize};
use url::Url;

/// The default proposer service endpoint
Expand Down
2 changes: 1 addition & 1 deletion crates/aggkit-prover-config/src/shutdown.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use serde::Serialize;
#[serde(rename_all = "kebab-case")]
pub struct ShutdownConfig {
#[serde(default = "default_shutdown_runtime_timeout")]
#[serde(with = "crate::with::HumanDuration")]
#[serde(with = "prover_utils::with::HumanDuration")]
pub runtime_timeout: Duration,
}

Expand Down
1 change: 1 addition & 0 deletions crates/aggkit-prover-types/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ license.workspace = true

[dependencies]
anyhow.workspace = true
aggchain-proof-core.workspace = true
bincode.workspace = true
prost = "0.13.4"
serde.workspace = true
Expand Down
Loading

0 comments on commit a44d5b6

Please sign in to comment.