Skip to content

Commit 7e8c5a9

Browse files
Implement builder ssz flow (#8)
* Impl builder ssz flow * Update cargo * fix header * Use lighthouse unstable and re-export only required crates * add logging * Debug * More debug * Remove all debugs * Update lighthouse version * Add ssz support to register_validators * Update lighthouse deps to add ssz support to SignedValidatorRegistrationData * Add tests for builder server endpoints * Remove debugs --------- Co-authored-by: Pawan Dhananjay <[email protected]>
1 parent bc7ae9e commit 7e8c5a9

File tree

8 files changed

+638
-88
lines changed

8 files changed

+638
-88
lines changed

Cargo.toml

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,21 +16,22 @@ members = [
1616

1717
[workspace.dependencies]
1818
async-trait = "0.1"
19-
axum = { version = "0.7", features = ["ws"] }
19+
axum = { version = "0.8", features = ["ws"] }
2020
bytes = "1.6"
21-
eth2 = { git = "https://github.com/sigp/lighthouse.git", rev = "c33307d70287fd3b7a70785f89dadcb737214903" }
21+
eth2 = { git = "https://github.com/sigp/lighthouse.git", rev = "3bc5f1f2a58b1df9454884672c8100fd5f79ba8b" }
2222
ethereum_serde_utils = "0.7"
2323
ethereum_ssz = "0.7"
2424
ethereum_ssz_derive = "0.7"
2525
flate2 = "1.0"
2626
futures = "0.3.30"
27-
http = "1"
28-
reqwest = { version = "0.12.5", features = ["json"] }
27+
http = "1.2"
28+
mediatype = "0.19.13"
29+
reqwest = { version = "0.12.12", features = ["json"] }
2930
serde = { version = "1.0", features = ["derive"] }
3031
serde_json = { version = "1", features = ["raw_value"] }
3132
superstruct = "0.8"
3233
tokio = { version = "1", default-features = false, features = ["signal", "rt-multi-thread", "macros"] }
3334
tokio-tungstenite = "0.24.0"
3435
tracing = { version = "0.1", features = ["attributes"] }
35-
types = { git = "https://github.com/sigp/lighthouse.git", rev = "c33307d70287fd3b7a70785f89dadcb737214903" }
36+
types = { git = "https://github.com/sigp/lighthouse.git", rev = "3bc5f1f2a58b1df9454884672c8100fd5f79ba8b" }
3637
rand = "0.8"

builder-client/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,5 @@ ethereum-apis-common = { path = "../common" }
99
reqwest.workspace = true
1010
serde.workspace = true
1111
serde_json.workspace = true
12+
ethereum_ssz.workspace = true
13+
axum.workspace = true

builder-client/src/lib.rs

Lines changed: 76 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,21 @@
1-
pub use builder_api_types::*;
1+
use axum::http::HeaderMap;
2+
use axum::http::HeaderValue;
3+
use builder_api_types::*;
24
pub use builder_bid::SignedBuilderBid;
5+
use ethereum_apis_common::ContentType;
36
pub use ethereum_apis_common::ErrorResponse;
7+
use reqwest::header::{ACCEPT, CONTENT_TYPE};
48
use reqwest::Client;
59
use reqwest::Url;
610
use serde::de::DeserializeOwned;
11+
use ssz::DecodeError;
12+
use ssz::Encode;
713

814
#[derive(Debug)]
915
pub enum Error {
1016
Reqwest(reqwest::Error),
1117
InvalidJson(serde_json::Error, String),
18+
InvalidSsz(DecodeError),
1219
ServerMessage(ErrorResponse),
1320
StatusCode(reqwest::StatusCode),
1421
InvalidUrl(Url),
@@ -34,6 +41,34 @@ impl BuilderClient {
3441
}
3542
}
3643

44+
async fn build_response_with_headers<T>(
45+
&self,
46+
response: reqwest::Response,
47+
content_type: ContentType,
48+
fork_name: ForkName,
49+
) -> Result<T, Error>
50+
where
51+
T: DeserializeOwned + ForkVersionDecode,
52+
{
53+
let status = response.status();
54+
let text = response.text().await?;
55+
56+
if status.is_success() {
57+
match content_type {
58+
ContentType::Json => {
59+
serde_json::from_str(&text).map_err(|e| Error::InvalidJson(e, text))
60+
}
61+
ContentType::Ssz => {
62+
T::from_ssz_bytes_by_fork(text.as_bytes(), fork_name).map_err(Error::InvalidSsz)
63+
}
64+
}
65+
} else {
66+
Err(Error::ServerMessage(
67+
serde_json::from_str(&text).map_err(|e| Error::InvalidJson(e, text))?,
68+
))
69+
}
70+
}
71+
3772
async fn build_response<T>(&self, response: reqwest::Response) -> Result<T, Error>
3873
where
3974
T: DeserializeOwned,
@@ -67,22 +102,50 @@ impl BuilderClient {
67102
pub async fn submit_blinded_block<E: EthSpec>(
68103
&self,
69104
block: &SignedBlindedBeaconBlock<E>,
105+
content_type: ContentType,
106+
fork_name: ForkName,
70107
) -> Result<ExecutionPayload<E>, Error> {
71108
let mut url = self.base_url.clone();
72109
url.path_segments_mut()
73110
.map_err(|_| Error::InvalidUrl(self.base_url.clone()))?
74111
.extend(&["eth", "v1", "builder", "blinded_blocks"]);
75112

76-
let response = self.client.post(url).json(block).send().await?;
77-
78-
self.build_response(response).await
113+
let mut headers = HeaderMap::new();
114+
headers.insert(
115+
CONTENT_TYPE,
116+
HeaderValue::from_str(&content_type.to_string()).unwrap(),
117+
);
118+
119+
let response = match content_type {
120+
ContentType::Json => {
121+
self.client
122+
.post(url)
123+
.headers(headers)
124+
.json(block)
125+
.send()
126+
.await?
127+
}
128+
ContentType::Ssz => {
129+
self.client
130+
.post(url)
131+
.headers(headers)
132+
.body(block.as_ssz_bytes())
133+
.send()
134+
.await?
135+
}
136+
};
137+
138+
self.build_response_with_headers(response, content_type, fork_name)
139+
.await
79140
}
80141

81142
pub async fn get_header<E: EthSpec>(
82143
&self,
83144
slot: Slot,
84145
parent_hash: ExecutionBlockHash,
85146
pubkey: &PublicKeyBytes,
147+
content_type: ContentType,
148+
fork_name: ForkName,
86149
) -> Result<SignedBuilderBid<E>, Error> {
87150
let mut url = self.base_url.clone();
88151
url.path_segments_mut()
@@ -97,9 +160,16 @@ impl BuilderClient {
97160
&pubkey.to_string(),
98161
]);
99162

100-
let response = self.client.get(url).send().await?;
163+
let mut headers = HeaderMap::new();
164+
headers.insert(
165+
ACCEPT,
166+
HeaderValue::from_str(&content_type.to_string()).unwrap(),
167+
);
101168

102-
self.build_response(response).await
169+
let response = self.client.get(url).headers(headers).send().await?;
170+
171+
self.build_response_with_headers(response, content_type, fork_name)
172+
.await
103173
}
104174

105175
pub async fn get_status(&self) -> Result<(), Error> {

builder-server/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,6 @@ serde.workspace = true
1717
serde_json.workspace = true
1818
tokio.workspace = true
1919
tracing.workspace = true
20+
21+
[dev-dependencies]
22+
tower = "0.5.2"

0 commit comments

Comments
 (0)