Skip to content
This repository has been archived by the owner on Jun 20, 2024. It is now read-only.

Commit

Permalink
Write proof output to directory in http mode
Browse files Browse the repository at this point in the history
  • Loading branch information
cpubot committed Nov 6, 2023
1 parent 8baee55 commit 3449956
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 35 deletions.
31 changes: 10 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,24 +53,13 @@ cargo run --bin leader -- --help
Usage: leader [OPTIONS]
Options:
-m, --mode <MODE>
The input mode. If `std-io`, the input is read from stdin. If `http`, the input is read from HTTP requests. If `jerigon`, the input is read from the `debug_traceBlockByNumber` and `eth_getBlockByNumber` RPC methods from Jerigon [default: std-io] [possible values: std-io, http, jerigon]
-p, --port <PORT>
The port to listen on when using the `http` mode [default: 8080]
--rpc-url <RPC_URL>
The RPC URL to use when using the `jerigon` mode
-b, --block-number <BLOCK_NUMBER>
The block number to use when using the `jerigon` mode
-t, --task-bus-routing-key <TASK_BUS_ROUTING_KEY>
Specifies the routing key for publishing task messages. In most cases, the default value should suffice [default: task]
-s, --serializer <SERIALIZER>
Determines the serialization format to be used [default: cbor] [possible values: cbor]
-r, --runtime <RUNTIME>
Specifies the runtime environment to use [default: amqp] [possible values: amqp, in-memory]
--amqp-uri <AMQP_URI>
Provides the URI for the AMQP broker, if the AMQP runtime is selected [env: AMQP_URI=amqp://localhost:5672]
-h, --help
Print help
-m, --mode <MODE> The input mode. If `std-io`, the input is read from stdin. If `http`, the input is read from HTTP requests. If `jerigon`, the input is read from the `debug_traceBlockByNumber` and `eth_getBlockByNumber` RPC methods from Jerigon [default: std-io] [possible values: std-io, http, jerigon]
-p, --port <PORT> The port to listen on when using the `http` mode [default: 8080]
-o, --output-dir <OUTPUT_DIR> The directory to which output should be written (`http` mode only)
--rpc-url <RPC_URL> The RPC URL to use when using the `jerigon` mode
-b, --block-number <BLOCK_NUMBER> The block number to use when using the `jerigon` mode
-r, --runtime <RUNTIME> Specifies the paladin runtime to use [default: amqp] [possible values: amqp, in-memory]
-h, --help Print help
```

### Paladin Runtime
Expand All @@ -92,15 +81,15 @@ RUST_LOG=debug cargo r --release --bin worker
Start the leader process with the desired [input mode](#input-mode). The default paladin runtime is AMQP, so no additional flags are required to enable it.

```bash
RUST_LOG=debug cargo r --release --bin leader -- --mode http
RUST_LOG=debug cargo r --release --bin leader -- --mode http --output-dir ./output
```

#### Starting an in-memory (single process) cluster

Paladin can emulate a cluster in memory within a single process. Useful for testing purposes.

```bash
RUST_LOG=debug cargo r --release --bin leader -- --mode http --runtime in-memory
RUST_LOG=debug cargo r --release --bin leader -- --mode http --runtime in-memory --output-dir ./output
```

### Input mode
Expand All @@ -120,7 +109,7 @@ cat ./block_121.json | RUST_LOG=debug cargo r --release --bin leader

Start the server
```bash
RUST_LOG=debug cargo r --release --bin leader -- --mode http
RUST_LOG=debug cargo r --release --bin leader -- --mode http --output-dir ./output
```

Once initialized, send a request:
Expand Down
16 changes: 11 additions & 5 deletions leader/src/cli.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use clap::{Parser, ValueEnum};
use paladin::config::Config;
use std::path::PathBuf;

use clap::{Parser, ValueEnum, ValueHint};
use paladin::config::Runtime;

#[derive(Parser)]
pub(crate) struct Cli {
Expand All @@ -12,14 +14,18 @@ pub(crate) struct Cli {
/// The port to listen on when using the `http` mode.
#[arg(short, long, default_value_t = 8080)]
pub(crate) port: u16,
/// The directory to which output should be written (`http` mode only).
#[arg(short, long, required_if_eq("mode", "http"), value_hint = ValueHint::DirPath)]
pub(crate) output_dir: Option<PathBuf>,
/// The RPC URL to use when using the `jerigon` mode.
#[arg(long, required_if_eq("mode", "jerigon"))]
#[arg(long, required_if_eq("mode", "jerigon"), value_hint = ValueHint::Url)]
pub(crate) rpc_url: Option<String>,
/// The block number to use when using the `jerigon` mode.
#[arg(short, long, required_if_eq("mode", "jerigon"))]
pub(crate) block_number: Option<u64>,
#[command(flatten)]
pub(crate) paladin_options: Config,
/// Specifies the paladin runtime to use.
#[arg(long, short, value_enum, default_value_t = Runtime::Amqp)]
pub(crate) runtime: Runtime,
}

#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, ValueEnum, Default)]
Expand Down
57 changes: 50 additions & 7 deletions leader/src/http.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
use std::{net::SocketAddr, sync::Arc};
use std::{net::SocketAddr, path::PathBuf, sync::Arc};

use anyhow::Result;
use anyhow::{bail, Result};
use axum::{http::StatusCode, routing::post, Json, Router};
use ethereum_types::U256;
use paladin::runtime::Runtime;
use plonky_block_proof_gen::proof_types::GeneratedBlockProof;
use serde_json::to_writer;
use tracing::{debug, error, info};

use crate::prover_input::ProverInput;

/// The main function for the HTTP mode.
pub(crate) async fn http_main(runtime: Runtime, port: u16) -> Result<()> {
pub(crate) async fn http_main(runtime: Runtime, port: u16, output_dir: PathBuf) -> Result<()> {
let addr = SocketAddr::from(([0, 0, 0, 0], port));
debug!("listening on {}", addr);

Expand All @@ -17,7 +20,7 @@ pub(crate) async fn http_main(runtime: Runtime, port: u16) -> Result<()> {
"/prove",
post({
let runtime = runtime.clone();
move |body| prove(body, runtime)
move |body| prove(body, runtime, output_dir.clone())
}),
);

Expand All @@ -26,13 +29,53 @@ pub(crate) async fn http_main(runtime: Runtime, port: u16) -> Result<()> {
.await?)
}

async fn prove(Json(payload): Json<ProverInput>, runtime: Arc<Runtime>) -> StatusCode {
/// Writes the generated block proof to a file.
///
/// Returns the fully qualified file name.
fn write_to_file(
output_dir: PathBuf,
block_number: U256,
generated_block_proof: &GeneratedBlockProof,
) -> Result<PathBuf> {
let file_name = format!("proof-{}.json", block_number);
let fully_qualified_file_name = output_dir.join(file_name);
let file = std::fs::File::create(fully_qualified_file_name.clone());

match file {
Ok(file) => {
to_writer(file, &generated_block_proof.intern)?;
Ok(fully_qualified_file_name)
}
Err(e) => {
bail!("Error while writing to file: {e:#?}");
}
}
}

async fn prove(
Json(payload): Json<ProverInput>,
runtime: Arc<Runtime>,
output_dir: PathBuf,
) -> StatusCode {
debug!("Received payload: {:#?}", payload);

let block_number = payload.other_data.b_data.b_meta.block_number;
info!("Proving block {block_number}");

match payload.prove(&runtime).await {
Ok(b_proof) => {
info!("Successfully proved {b_proof:#?}");
StatusCode::OK
info!("Successfully proved block {block_number}");

match write_to_file(output_dir, block_number, &b_proof) {
Ok(file) => {
info!("Successfully wrote proof to {}", file.display());
StatusCode::OK
}
Err(e) => {
error!("{e}");
StatusCode::INTERNAL_SERVER_ERROR
}
}
}
Err(e) => {
error!("Error while proving: {e:#?}");
Expand Down
18 changes: 16 additions & 2 deletions leader/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,28 @@ async fn main() -> Result<()> {
init::tracing();

let args = cli::Cli::parse();
let runtime = Runtime::from_config::<Ops>(&args.paladin_options).await?;
let runtime = Runtime::from_config::<Ops>(&paladin::config::Config {
runtime: args.runtime,
..Default::default()
})
.await?;

match args.mode {
Mode::StdIo => {
stdio::stdio_main(runtime).await?;
}
Mode::Http => {
http::http_main(runtime, args.port).await?;
let output_dir = args
.output_dir
.expect("output-dir is required in http mode");

// check if output_dir exists, is a directory, and is writable
let output_dir_metadata = std::fs::metadata(&output_dir)?;
if !output_dir.is_dir() || output_dir_metadata.permissions().readonly() {
panic!("output-dir is not a writable directory");
}

http::http_main(runtime, args.port, output_dir).await?;
}
Mode::Jerigon => {
let rpc_url = args.rpc_url.expect("rpc-url is required in jerigon mode");
Expand Down

0 comments on commit 3449956

Please sign in to comment.