Skip to content

Commit 157019c

Browse files
committed
add common crate and builder server
1 parent a696b28 commit 157019c

File tree

14 files changed

+504
-244
lines changed

14 files changed

+504
-244
lines changed

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@
22
resolver = "2"
33
members = [
44
"builder-api-types",
5+
"builder-server",
56
"relay-client",
67
"beacon-client",
78
"relay-api-types",
89
"beacon-api-types",
910
"relay-server",
11+
"common"
1012
]
1113

1214
[workspace.dependencies]

builder-server/Cargo.toml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
[package]
2+
name = "builder-server"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[dependencies]
7+
async-trait.workspace = true
8+
axum.workspace = true
9+
bytes.workspace = true
10+
ethereum_ssz.workspace = true
11+
flate2.workspace = true
12+
futures.workspace = true
13+
http.workspace = true
14+
builder-api-types = { path = "../builder-api-types" }
15+
ethereum-apis-common = { path = "../common" }
16+
serde.workspace = true
17+
serde_json.workspace = true
18+
tokio.workspace = true
19+
tracing.workspace = true
20+
types.workspace = true

builder-server/src/builder.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
use async_trait::async_trait;
2+
use ethereum_apis_common::ErrorResponse;
3+
use types::{
4+
builder_bid::SignedBuilderBid, eth_spec::EthSpec, ExecutionBlockHash, ExecutionPayload,
5+
ForkName, PublicKeyBytes, SignedBlindedBeaconBlock, SignedValidatorRegistrationData, Slot,
6+
};
7+
8+
#[async_trait]
9+
pub trait Builder<E: EthSpec> {
10+
async fn register_validators(
11+
&self,
12+
registrations: Vec<SignedValidatorRegistrationData>,
13+
) -> Result<(), ErrorResponse>;
14+
15+
async fn submit_blinded_block(
16+
&self,
17+
block: SignedBlindedBeaconBlock<E>,
18+
) -> Result<ExecutionPayload<E>, ErrorResponse>;
19+
20+
async fn get_header(
21+
&self,
22+
slot: Slot,
23+
parent_hash: ExecutionBlockHash,
24+
pubkey: PublicKeyBytes,
25+
) -> Result<SignedBuilderBid<E>, ErrorResponse>;
26+
27+
fn fork_name_at_slot(&self, slot: Slot) -> ForkName;
28+
}

builder-server/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
pub use builder_api_types::*;
2+
3+
pub mod builder;
4+
pub mod server;

builder-server/src/server.rs

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
use axum::{
2+
body::Body,
3+
extract::{Path, State},
4+
http::StatusCode,
5+
response::Response,
6+
routing::{get, post},
7+
Json, Router,
8+
};
9+
use ethereum_apis_common::build_response;
10+
use types::{
11+
eth_spec::EthSpec, fork_versioned_response::EmptyMetadata, ExecutionBlockHash,
12+
ForkVersionedResponse, PublicKeyBytes, SignedBlindedBeaconBlock,
13+
SignedValidatorRegistrationData, Slot,
14+
};
15+
16+
use crate::builder::Builder;
17+
18+
pub fn new<I, A, E>(api_impl: I) -> Router
19+
where
20+
E: EthSpec,
21+
I: AsRef<A> + Clone + Send + Sync + 'static,
22+
A: Builder<E> + 'static,
23+
{
24+
Router::new()
25+
.route(
26+
"/eth/v1/builder/validators",
27+
post(register_validators::<I, A, E>),
28+
)
29+
.route(
30+
"/eth/v1/builder/blinded_blocks",
31+
post(submit_blinded_block::<I, A, E>),
32+
)
33+
.route("/eth/v1/builder/status", get(get_status))
34+
.route(
35+
"/eth/v1/builder/header/:slot/:parent_hash/:pubkey",
36+
get(get_header::<I, A, E>),
37+
)
38+
.with_state(api_impl)
39+
}
40+
41+
async fn register_validators<I, A, E>(
42+
State(api_impl): State<I>,
43+
Json(registrations): Json<Vec<SignedValidatorRegistrationData>>,
44+
) -> Result<Response<Body>, StatusCode>
45+
where
46+
E: EthSpec,
47+
I: AsRef<A> + Send + Sync,
48+
A: Builder<E>,
49+
{
50+
let res = api_impl.as_ref().register_validators(registrations).await;
51+
build_response(res).await
52+
}
53+
54+
async fn submit_blinded_block<I, A, E>(
55+
State(api_impl): State<I>,
56+
Json(block): Json<SignedBlindedBeaconBlock<E>>,
57+
) -> Result<Response<Body>, StatusCode>
58+
where
59+
E: EthSpec,
60+
I: AsRef<A> + Send + Sync,
61+
A: Builder<E>,
62+
{
63+
let res = api_impl
64+
.as_ref()
65+
.submit_blinded_block(block)
66+
.await
67+
.map(|payload| ForkVersionedResponse {
68+
version: Some(payload.fork_name()),
69+
metadata: EmptyMetadata {},
70+
data: payload,
71+
});
72+
build_response(res).await
73+
}
74+
75+
async fn get_status() -> StatusCode {
76+
StatusCode::OK
77+
}
78+
79+
async fn get_header<I, A, E>(
80+
State(api_impl): State<I>,
81+
Path((slot, parent_hash, pubkey)): Path<(Slot, ExecutionBlockHash, PublicKeyBytes)>,
82+
) -> Result<Response<Body>, StatusCode>
83+
where
84+
E: EthSpec,
85+
I: AsRef<A> + Send + Sync,
86+
A: Builder<E>,
87+
{
88+
let res = api_impl
89+
.as_ref()
90+
.get_header(slot, parent_hash, pubkey)
91+
.await
92+
.map(|signed_bid| ForkVersionedResponse {
93+
version: Some(api_impl.as_ref().fork_name_at_slot(slot)),
94+
metadata: EmptyMetadata {},
95+
data: signed_bid,
96+
});
97+
build_response(res).await
98+
}

common/Cargo.toml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
[package]
2+
name = "ethereum-apis-common"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[dependencies]
7+
async-trait.workspace = true
8+
axum.workspace = true
9+
bytes.workspace = true
10+
ethereum_ssz.workspace = true
11+
flate2.workspace = true
12+
futures.workspace = true
13+
http.workspace = true
14+
serde.workspace = true
15+
serde_json.workspace = true
16+
tokio.workspace = true
17+
tracing.workspace = true
18+
types.workspace = true

0 commit comments

Comments
 (0)