@@ -9,7 +9,8 @@ use axum::{
99 Json , Router ,
1010} ;
1111use builder_api_types:: {
12- eth_spec:: EthSpec , ExecutionBlockHash , PublicKeyBytes , SignedBlindedBeaconBlock ,
12+ eth_spec:: EthSpec , fork_versioned_response:: ForkVersionDecode , ExecutionBlockHash , ForkName ,
13+ FullPayloadContents , MainnetEthSpec , PublicKeyBytes , SignedBlindedBeaconBlock ,
1314 SignedValidatorRegistrationData , Slot ,
1415} ;
1516use ethereum_apis_common:: {
4041 )
4142 . route ( "/eth/v1/builder/status" , get ( get_status) )
4243 . route (
43- "/eth/v1/builder/header/: slot/: parent_hash/: pubkey" ,
44+ "/eth/v1/builder/header/{ slot}/{ parent_hash}/{ pubkey} " ,
4445 get ( get_header :: < I , A , E > ) ,
4546 )
4647 . with_state ( api_impl)
@@ -69,20 +70,22 @@ where
6970 I : AsRef < A > + Send + Sync ,
7071 A : Builder < E > ,
7172{
73+ dbg ! ( & headers) ;
7274 let content_type_header = headers. get ( CONTENT_TYPE ) ;
7375 let content_type = content_type_header. and_then ( |value| value. to_str ( ) . ok ( ) ) ;
7476 let content_type = match content_type {
7577 Some ( "application/octet-stream" ) => ContentType :: Ssz ,
7678 _ => ContentType :: Json ,
7779 } ;
7880 let slot = block. slot ( ) ;
81+
7982 let res = api_impl. as_ref ( ) . submit_blinded_block ( block) . await ;
8083
81- dbg ! ( "in submit_blinded_block" ) ;
84+ println ! ( "in submit_blinded_block" ) ;
8285 let response =
8386 build_response_with_headers ( res, content_type, api_impl. as_ref ( ) . fork_name_at_slot ( slot) )
8487 . await ;
85- dbg ! ( & response) ;
88+ println ! ( "Got response ok {}" , response . is_ok ( ) ) ;
8689 response
8790}
8891
@@ -122,3 +125,110 @@ where
122125 tracing:: info!( "Got response from builder, constructing response" ) ;
123126 build_response_with_headers ( res, content_type, api_impl. as_ref ( ) . fork_name_at_slot ( slot) ) . await
124127}
128+
129+ #[ cfg( test) ]
130+ mod tests {
131+ use super :: * ;
132+ use async_trait:: async_trait;
133+ use axum:: { body:: Body , http:: Request } ;
134+ use builder_api_types:: {
135+ builder_bid:: SignedBuilderBid , BeaconBlock , BeaconBlockDeneb , Blob , BlobsBundle ,
136+ EmptyBlock , ExecutionPayload , ExecutionPayloadAndBlobs , ExecutionPayloadDeneb , ForkName ,
137+ ForkVersionDecode , FullPayloadContents , KzgCommitment , KzgProof , MainnetEthSpec , Signature ,
138+ } ;
139+ use ethereum_apis_common:: { ErrorResponse , CONSENSUS_VERSION_HEADER } ;
140+ use http:: HeaderValue ;
141+ use ssz:: Encode ;
142+ use std:: { marker:: PhantomData , usize} ;
143+ use tower:: ServiceExt ;
144+
145+ #[ derive( Clone ) ]
146+ struct DummyBuilder < E : EthSpec > {
147+ _phantom : PhantomData < E > ,
148+ }
149+
150+ impl < E : EthSpec > AsRef < DummyBuilder < E > > for DummyBuilder < E > {
151+ fn as_ref ( & self ) -> & DummyBuilder < E > {
152+ self
153+ }
154+ }
155+
156+ #[ async_trait]
157+ impl < E : EthSpec > Builder < E > for DummyBuilder < E > {
158+ fn fork_name_at_slot ( & self , _slot : Slot ) -> builder_api_types:: ForkName {
159+ ForkName :: Deneb
160+ }
161+
162+ async fn get_header (
163+ & self ,
164+ _slot : Slot ,
165+ _parent_hash : ExecutionBlockHash ,
166+ _pubkey : PublicKeyBytes ,
167+ ) -> Result < SignedBuilderBid < E > , ErrorResponse > {
168+ todo ! ( )
169+ }
170+
171+ async fn register_validators (
172+ & self ,
173+ _registrations : Vec < SignedValidatorRegistrationData > ,
174+ ) -> Result < ( ) , ErrorResponse > {
175+ Ok ( ( ) )
176+ }
177+
178+ async fn submit_blinded_block (
179+ & self ,
180+ _block : SignedBlindedBeaconBlock < E > ,
181+ ) -> Result < FullPayloadContents < E > , ErrorResponse > {
182+ let payload_and_blobs: ExecutionPayloadAndBlobs < E > = ExecutionPayloadAndBlobs {
183+ blobs_bundle : BlobsBundle {
184+ commitments : vec ! [ KzgCommitment :: empty_for_testing( ) ] . into ( ) ,
185+ proofs : vec ! [ KzgProof :: empty( ) ] . into ( ) ,
186+ blobs : vec ! [ Blob :: <E >:: new( vec![ 42 ; E :: bytes_per_blob( ) ] ) . unwrap( ) ] . into ( ) ,
187+ } ,
188+ execution_payload : ExecutionPayload :: Deneb ( ExecutionPayloadDeneb {
189+ ..Default :: default ( )
190+ } ) ,
191+ } ;
192+ let full_payload = FullPayloadContents :: PayloadAndBlobs ( payload_and_blobs) ;
193+ Ok ( full_payload)
194+ }
195+ }
196+
197+ #[ tokio:: test]
198+ async fn test_api ( ) {
199+ let app = new ( DummyBuilder :: < MainnetEthSpec > {
200+ _phantom : PhantomData ,
201+ } ) ;
202+
203+ let spec = MainnetEthSpec :: default_spec ( ) ;
204+ let dummy_block = SignedBlindedBeaconBlock :: < MainnetEthSpec > :: from_block (
205+ BeaconBlock :: Deneb ( BeaconBlockDeneb :: empty ( & spec) ) ,
206+ Signature :: empty ( ) ,
207+ ) ;
208+ let request = Request :: builder ( )
209+ . uri ( "/eth/v1/builder/blinded_blocks" )
210+ . method ( "POST" )
211+ . header (
212+ CONTENT_TYPE ,
213+ HeaderValue :: from_static ( "application/octet-stream" ) ,
214+ )
215+ . header ( CONSENSUS_VERSION_HEADER , HeaderValue :: from_static ( "deneb" ) )
216+ . body ( Body :: from ( dummy_block. as_ssz_bytes ( ) ) )
217+ . unwrap ( ) ;
218+
219+ let response = app. oneshot ( request) . await . unwrap ( ) ;
220+
221+ // Assert status code
222+ // assert_eq!(response.status(), StatusCode::ACCEPTED);
223+
224+ // Get response body as bytes
225+ let body = axum:: body:: to_bytes ( response. into_body ( ) , usize:: MAX )
226+ . await
227+ . unwrap ( ) ;
228+
229+ dbg ! (
230+ FullPayloadContents :: <MainnetEthSpec >:: from_ssz_bytes_by_fork( & body, ForkName :: Deneb )
231+ . unwrap( )
232+ ) ;
233+ }
234+ }
0 commit comments