@@ -12,6 +12,7 @@ mod proposer_duties;
1212mod state_id;
1313mod sync_committees;
1414mod validator_inclusion;
15+ mod version;
1516
1617use beacon_chain:: {
1718 attestation_verification:: SignatureVerifiedAttestation ,
@@ -21,7 +22,7 @@ use beacon_chain::{
2122 WhenSlotSkipped ,
2223} ;
2324use block_id:: BlockId ;
24- use eth2:: types:: { self as api_types, ValidatorId } ;
25+ use eth2:: types:: { self as api_types, EndpointVersion , ValidatorId } ;
2526use eth2_libp2p:: { types:: SyncState , EnrExt , NetworkGlobals , PeerId , PubsubMessage } ;
2627use lighthouse_version:: version_with_platform;
2728use network:: NetworkMessage ;
@@ -43,14 +44,14 @@ use types::{
4344 SignedContributionAndProof , SignedVoluntaryExit , Slot , SyncCommitteeMessage ,
4445 SyncContributionData ,
4546} ;
47+ use version:: { fork_versioned_response, unsupported_version_rejection, V1 } ;
4648use warp:: http:: StatusCode ;
4749use warp:: sse:: Event ;
4850use warp:: Reply ;
4951use warp:: { http:: Response , Filter } ;
5052use warp_utils:: task:: { blocking_json_task, blocking_task} ;
5153
5254const API_PREFIX : & str = "eth" ;
53- const API_VERSION : & str = "v1" ;
5455
5556/// If the node is within this many epochs from the head, we declare it to be synced regardless of
5657/// the network sync state.
@@ -154,38 +155,38 @@ pub fn prometheus_metrics() -> warp::filters::log::Log<impl Fn(warp::filters::lo
154155 // a block hash).
155156 let path = {
156157 let equals = |s : & ' static str | -> Option < & ' static str > {
157- if info. path ( ) == format ! ( "/{}/{}/{} " , API_PREFIX , API_VERSION , s) {
158+ if info. path ( ) == format ! ( "/{}/{}" , API_PREFIX , s) {
158159 Some ( s)
159160 } else {
160161 None
161162 }
162163 } ;
163164
164165 let starts_with = |s : & ' static str | -> Option < & ' static str > {
165- if info
166- . path ( )
167- . starts_with ( & format ! ( "/{}/{}/{}" , API_PREFIX , API_VERSION , s) )
168- {
166+ if info. path ( ) . starts_with ( & format ! ( "/{}/{}" , API_PREFIX , s) ) {
169167 Some ( s)
170168 } else {
171169 None
172170 }
173171 } ;
174172
175- equals ( "beacon/blocks" )
176- . or_else ( || starts_with ( "validator/duties/attester" ) )
177- . or_else ( || starts_with ( "validator/duties/proposer" ) )
178- . or_else ( || starts_with ( "validator/attestation_data" ) )
179- . or_else ( || starts_with ( "validator/blocks" ) )
180- . or_else ( || starts_with ( "validator/aggregate_attestation" ) )
181- . or_else ( || starts_with ( "validator/aggregate_and_proofs" ) )
182- . or_else ( || starts_with ( "validator/beacon_committee_subscriptions" ) )
183- . or_else ( || starts_with ( "beacon/" ) )
184- . or_else ( || starts_with ( "config/" ) )
185- . or_else ( || starts_with ( "debug/" ) )
186- . or_else ( || starts_with ( "events/" ) )
187- . or_else ( || starts_with ( "node/" ) )
188- . or_else ( || starts_with ( "validator/" ) )
173+ // First line covers `POST /v1/beacon/blocks` only
174+ equals ( "v1/beacon/blocks" )
175+ . or_else ( || starts_with ( "v1/validator/duties/attester" ) )
176+ . or_else ( || starts_with ( "v1/validator/duties/proposer" ) )
177+ . or_else ( || starts_with ( "v1/validator/attestation_data" ) )
178+ . or_else ( || starts_with ( "v1/validator/blocks" ) )
179+ . or_else ( || starts_with ( "v2/validator/blocks" ) )
180+ . or_else ( || starts_with ( "v1/validator/aggregate_attestation" ) )
181+ . or_else ( || starts_with ( "v1/validator/aggregate_and_proofs" ) )
182+ . or_else ( || starts_with ( "v1/validator/beacon_committee_subscriptions" ) )
183+ . or_else ( || starts_with ( "v1/beacon/" ) )
184+ . or_else ( || starts_with ( "v2/beacon/" ) )
185+ . or_else ( || starts_with ( "v1/config/" ) )
186+ . or_else ( || starts_with ( "v1/debug/" ) )
187+ . or_else ( || starts_with ( "v1/events/" ) )
188+ . or_else ( || starts_with ( "v1/node/" ) )
189+ . or_else ( || starts_with ( "v1/validator/" ) )
189190 . unwrap_or ( "other" )
190191 } ;
191192
@@ -241,7 +242,30 @@ pub fn serve<T: BeaconChainTypes>(
241242 ) ) ;
242243 }
243244
244- let eth1_v1 = warp:: path ( API_PREFIX ) . and ( warp:: path ( API_VERSION ) ) ;
245+ // Create a filter that extracts the endpoint version.
246+ let any_version = warp:: path ( API_PREFIX ) . and ( warp:: path:: param :: < EndpointVersion > ( ) . or_else (
247+ |_| async move {
248+ Err ( warp_utils:: reject:: custom_bad_request (
249+ "Invalid version identifier" . to_string ( ) ,
250+ ) )
251+ } ,
252+ ) ) ;
253+
254+ // Filter that enforces a single endpoint version and then discards the `EndpointVersion`.
255+ let single_version = |reqd : EndpointVersion | {
256+ any_version
257+ . clone ( )
258+ . and_then ( move |version| async move {
259+ if version == reqd {
260+ Ok ( ( ) )
261+ } else {
262+ Err ( unsupported_version_rejection ( version) )
263+ }
264+ } )
265+ . untuple_one ( )
266+ } ;
267+
268+ let eth1_v1 = single_version ( V1 ) ;
245269
246270 // Create a `warp` filter that provides access to the network globals.
247271 let inner_network_globals = ctx. network_globals . clone ( ) ;
@@ -877,23 +901,32 @@ pub fn serve<T: BeaconChainTypes>(
877901 } ,
878902 ) ;
879903
880- let beacon_blocks_path = eth1_v1
904+ let block_id_or_err = warp:: path:: param :: < BlockId > ( ) . or_else ( |_| async {
905+ Err ( warp_utils:: reject:: custom_bad_request (
906+ "Invalid block ID" . to_string ( ) ,
907+ ) )
908+ } ) ;
909+
910+ let beacon_blocks_path_v1 = eth1_v1
881911 . and ( warp:: path ( "beacon" ) )
882912 . and ( warp:: path ( "blocks" ) )
883- . and ( warp:: path:: param :: < BlockId > ( ) . or_else ( |_| async {
884- Err ( warp_utils:: reject:: custom_bad_request (
885- "Invalid block ID" . to_string ( ) ,
886- ) )
887- } ) )
913+ . and ( block_id_or_err. clone ( ) )
914+ . and ( chain_filter. clone ( ) ) ;
915+
916+ let beacon_blocks_path_any = any_version
917+ . and ( warp:: path ( "beacon" ) )
918+ . and ( warp:: path ( "blocks" ) )
919+ . and ( block_id_or_err)
888920 . and ( chain_filter. clone ( ) ) ;
889921
890922 // GET beacon/blocks/{block_id}
891- let get_beacon_block = beacon_blocks_path
923+ let get_beacon_block = beacon_blocks_path_any
892924 . clone ( )
893925 . and ( warp:: path:: end ( ) )
894926 . and ( warp:: header:: optional :: < api_types:: Accept > ( "accept" ) )
895927 . and_then (
896- |block_id : BlockId ,
928+ |endpoint_version : EndpointVersion ,
929+ block_id : BlockId ,
897930 chain : Arc < BeaconChain < T > > ,
898931 accept_header : Option < api_types:: Accept > | {
899932 blocking_task ( move || {
@@ -909,17 +942,18 @@ pub fn serve<T: BeaconChainTypes>(
909942 e
910943 ) )
911944 } ) ,
912- _ => Ok (
913- warp:: reply:: json ( & api_types:: GenericResponseRef :: from ( & block) )
914- . into_response ( ) ,
915- ) ,
945+ _ => {
946+ let fork_name = block. fork_name ( & chain. spec ) . ok ( ) ;
947+ fork_versioned_response ( endpoint_version, fork_name, block)
948+ . map ( |res| warp:: reply:: json ( & res) . into_response ( ) )
949+ }
916950 }
917951 } )
918952 } ,
919953 ) ;
920954
921955 // GET beacon/blocks/{block_id}/root
922- let get_beacon_block_root = beacon_blocks_path
956+ let get_beacon_block_root = beacon_blocks_path_v1
923957 . clone ( )
924958 . and ( warp:: path ( "root" ) )
925959 . and ( warp:: path:: end ( ) )
@@ -933,7 +967,7 @@ pub fn serve<T: BeaconChainTypes>(
933967 } ) ;
934968
935969 // GET beacon/blocks/{block_id}/attestations
936- let get_beacon_block_attestations = beacon_blocks_path
970+ let get_beacon_block_attestations = beacon_blocks_path_v1
937971 . clone ( )
938972 . and ( warp:: path ( "attestations" ) )
939973 . and ( warp:: path:: end ( ) )
@@ -1331,7 +1365,8 @@ pub fn serve<T: BeaconChainTypes>(
13311365 */
13321366
13331367 // GET debug/beacon/states/{state_id}
1334- let get_debug_beacon_states = eth1_v1
1368+ let get_debug_beacon_states = any_version
1369+ . clone ( )
13351370 . and ( warp:: path ( "debug" ) )
13361371 . and ( warp:: path ( "beacon" ) )
13371372 . and ( warp:: path ( "states" ) )
@@ -1344,7 +1379,8 @@ pub fn serve<T: BeaconChainTypes>(
13441379 . and ( warp:: header:: optional :: < api_types:: Accept > ( "accept" ) )
13451380 . and ( chain_filter. clone ( ) )
13461381 . and_then (
1347- |state_id : StateId ,
1382+ |endpoint_version : EndpointVersion ,
1383+ state_id : StateId ,
13481384 accept_header : Option < api_types:: Accept > ,
13491385 chain : Arc < BeaconChain < T > > | {
13501386 blocking_task ( move || match accept_header {
@@ -1362,10 +1398,9 @@ pub fn serve<T: BeaconChainTypes>(
13621398 } )
13631399 }
13641400 _ => state_id. map_state ( & chain, |state| {
1365- Ok (
1366- warp:: reply:: json ( & api_types:: GenericResponseRef :: from ( & state) )
1367- . into_response ( ) ,
1368- )
1401+ let fork_name = state. fork_name ( & chain. spec ) . ok ( ) ;
1402+ let res = fork_versioned_response ( endpoint_version, fork_name, & state) ?;
1403+ Ok ( warp:: reply:: json ( & res) . into_response ( ) )
13691404 } ) ,
13701405 } )
13711406 } ,
@@ -1685,7 +1720,8 @@ pub fn serve<T: BeaconChainTypes>(
16851720 } ) ;
16861721
16871722 // GET validator/blocks/{slot}
1688- let get_validator_blocks = eth1_v1
1723+ let get_validator_blocks = any_version
1724+ . clone ( )
16891725 . and ( warp:: path ( "validator" ) )
16901726 . and ( warp:: path ( "blocks" ) )
16911727 . and ( warp:: path:: param :: < Slot > ( ) . or_else ( |_| async {
@@ -1698,7 +1734,10 @@ pub fn serve<T: BeaconChainTypes>(
16981734 . and ( warp:: query :: < api_types:: ValidatorBlocksQuery > ( ) )
16991735 . and ( chain_filter. clone ( ) )
17001736 . and_then (
1701- |slot : Slot , query : api_types:: ValidatorBlocksQuery , chain : Arc < BeaconChain < T > > | {
1737+ |endpoint_version : EndpointVersion ,
1738+ slot : Slot ,
1739+ query : api_types:: ValidatorBlocksQuery ,
1740+ chain : Arc < BeaconChain < T > > | {
17021741 blocking_json_task ( move || {
17031742 let randao_reveal = ( & query. randao_reveal ) . try_into ( ) . map_err ( |e| {
17041743 warp_utils:: reject:: custom_bad_request ( format ! (
@@ -1707,11 +1746,11 @@ pub fn serve<T: BeaconChainTypes>(
17071746 ) )
17081747 } ) ?;
17091748
1710- chain
1749+ let ( block , _ ) = chain
17111750 . produce_block ( randao_reveal, slot, query. graffiti . map ( Into :: into) )
1712- . map ( |block_and_state| block_and_state . 0 )
1713- . map ( api_types :: GenericResponse :: from )
1714- . map_err ( warp_utils :: reject :: block_production_error )
1751+ . map_err ( warp_utils :: reject :: block_production_error ) ? ;
1752+ let fork_name = block . to_ref ( ) . fork_name ( & chain . spec ) . ok ( ) ;
1753+ fork_versioned_response ( endpoint_version , fork_name , block )
17151754 } )
17161755 } ,
17171756 ) ;
0 commit comments