Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add engine_getPayloadV2 #3646

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 38 additions & 2 deletions beacon_node/execution_layer/src/engine_api/http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ pub const ENGINE_NEW_PAYLOAD_TIMEOUT: Duration = Duration::from_secs(8);
pub const ENGINE_GET_PAYLOAD_V1: &str = "engine_getPayloadV1";
pub const ENGINE_GET_PAYLOAD_TIMEOUT: Duration = Duration::from_secs(2);

pub const ENGINE_GET_PAYLOAD_V2: &str = "engine_getPayloadV2";

pub const ENGINE_FORKCHOICE_UPDATED_V1: &str = "engine_forkchoiceUpdatedV1";
pub const ENGINE_FORKCHOICE_UPDATED_TIMEOUT: Duration = Duration::from_secs(8);

Expand Down Expand Up @@ -515,6 +517,14 @@ pub mod deposit_methods {
}
}

pub enum GetPayloadResponse<T: EthSpec> {
V1(ExecutionPayload<T>),
V2 {
payload: ExecutionPayload<T>,
block_value: Uint256,
},
}

pub struct HttpJsonRpc {
pub client: Client,
pub url: SensitiveUrl,
Expand Down Expand Up @@ -651,17 +661,43 @@ impl HttpJsonRpc {
Ok(response.into())
}

pub async fn get_payload<T: EthSpec>(
&self,
payload_id: PayloadId,
) -> Result<GetPayloadResponse<T>, Error> {
match self.get_payload_v2(payload_id).await {
Err(_) => self.get_payload_v2(payload_id).await,
Ok(resp) => Ok(resp),
}
}

pub async fn get_payload_v1<T: EthSpec>(
&self,
payload_id: PayloadId,
) -> Result<ExecutionPayload<T>, Error> {
) -> Result<GetPayloadResponse<T>, Error> {
let params = json!([JsonPayloadIdRequest::from(payload_id)]);

let response: JsonExecutionPayloadV1<T> = self
.rpc_request(ENGINE_GET_PAYLOAD_V1, params, ENGINE_GET_PAYLOAD_TIMEOUT)
.await?;

Ok(response.into())
Ok(GetPayloadResponse::V1(response.into()))
}

pub async fn get_payload_v2<T: EthSpec>(
&self,
payload_id: PayloadId,
) -> Result<GetPayloadResponse<T>, Error> {
let params = json!([JsonPayloadIdRequest::from(payload_id)]);

let response: JsonExecutionPayloadV2<T> = self
.rpc_request(ENGINE_GET_PAYLOAD_V2, params, ENGINE_GET_PAYLOAD_TIMEOUT)
.await?;

Ok(GetPayloadResponse::V2 {
payload: response.execution_payload_v1.into(),
block_value: response.block_value,
})
}

pub async fn forkchoice_updated_v1(
Expand Down
8 changes: 8 additions & 0 deletions beacon_node/execution_layer/src/engine_api/json_structures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,14 @@ impl<T: EthSpec> From<JsonExecutionPayloadHeaderV1<T>> for ExecutionPayloadHeade
}
}

#[derive(Debug, PartialEq, Default, Serialize, Deserialize)]
#[serde(bound = "T: EthSpec", rename_all = "camelCase")]
pub struct JsonExecutionPayloadV2<T: EthSpec> {
pub execution_payload_v1: JsonExecutionPayloadV1<T>,
#[serde(with = "eth2_serde_utils::u256_hex_be")]
pub block_value: Uint256,
}

#[derive(Debug, PartialEq, Default, Serialize, Deserialize)]
#[serde(bound = "T: EthSpec", rename_all = "camelCase")]
pub struct JsonExecutionPayloadV1<T: EthSpec> {
Expand Down
41 changes: 30 additions & 11 deletions beacon_node/execution_layer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
//! This crate only provides useful functionality for "The Merge", it does not provide any of the
//! deposit-contract functionality that the `beacon_node/eth1` crate already provides.

use crate::http::GetPayloadResponse;
use crate::payload_cache::PayloadCache;
use auth::{strip_prefix, Auth, JwtKey};
use builder_client::BuilderHttpClient;
Expand Down Expand Up @@ -607,7 +608,7 @@ impl<T: EthSpec> ExecutionLayer<T> {
);
let (relay_result, local_result) = tokio::join!(
builder.get_builder_header::<T, Payload>(slot, parent_hash, &pubkey),
self.get_full_payload_caching(
self.get_full_payload_caching::<Payload>(
parent_hash,
timestamp,
prev_randao,
Expand All @@ -617,23 +618,23 @@ impl<T: EthSpec> ExecutionLayer<T> {
);

return match (relay_result, local_result) {
(Err(e), Ok(local)) => {
(Err(e), Ok((local, _))) => {
warn!(
self.log(),
"Unable to retrieve a payload from a connected \
builder, falling back to the local execution client: {e:?}"
);
Ok(local)
}
(Ok(None), Ok(local)) => {
(Ok(None), Ok((local, _))) => {
info!(
self.log(),
"No payload provided by connected builder. \
Attempting to propose through local execution engine"
);
Ok(local)
}
(Ok(Some(relay)), Ok(local)) => {
(Ok(Some(relay)), Ok((local, local_block_value))) => {
let is_signature_valid = relay.data.verify_signature(spec);
let header = relay.data.message.header;

Expand All @@ -645,6 +646,18 @@ impl<T: EthSpec> ExecutionLayer<T> {

let relay_value = relay.data.message.value;
let configured_value = self.inner.builder_profit_threshold;

if let Some(local_value) = local_block_value {
if local_value >= relay_value {
info!(
self.log(),
"Local block is more profitable than relay block";
"local_block_value" => %local_value,
"relay_value" => %relay_value
);
return Ok(local)
}
}
if relay_value < configured_value {
info!(
self.log(),
Expand Down Expand Up @@ -738,7 +751,7 @@ impl<T: EthSpec> ExecutionLayer<T> {
suggested_fee_recipient,
forkchoice_update_params,
)
.await
.await.map(|res| res.0)
}

/// Get a full payload without caching its result in the execution layer's payload cache.
Expand All @@ -758,7 +771,7 @@ impl<T: EthSpec> ExecutionLayer<T> {
forkchoice_update_params,
noop,
)
.await
.await.map(|res| res.0)
}

/// Get a full payload and cache its result in the execution layer's payload cache.
Expand All @@ -769,7 +782,7 @@ impl<T: EthSpec> ExecutionLayer<T> {
prev_randao: Hash256,
suggested_fee_recipient: Address,
forkchoice_update_params: ForkchoiceUpdateParameters,
) -> Result<Payload, Error> {
) -> Result<(Payload, Option<Uint256>), Error> {
self.get_full_payload_with(
parent_hash,
timestamp,
Expand All @@ -789,7 +802,7 @@ impl<T: EthSpec> ExecutionLayer<T> {
suggested_fee_recipient: Address,
forkchoice_update_params: ForkchoiceUpdateParameters,
f: fn(&ExecutionLayer<T>, &ExecutionPayload<T>) -> Option<ExecutionPayload<T>>,
) -> Result<Payload, Error> {
) -> Result<(Payload, Option<Uint256>), Error> {
debug!(
self.log(),
"Issuing engine_getPayload";
Expand Down Expand Up @@ -857,9 +870,15 @@ impl<T: EthSpec> ExecutionLayer<T> {

engine
.api
.get_payload_v1::<T>(payload_id)
.get_payload::<T>(payload_id)
.await
.map(|full_payload| {
.map(|response| {
let (full_payload, block_value) = match response {
GetPayloadResponse::V1(full_payload) => (full_payload, None),
GetPayloadResponse::V2 { payload, block_value } =>
(payload, Some(block_value))

};
if full_payload.fee_recipient != suggested_fee_recipient {
error!(
self.log(),
Expand All @@ -880,7 +899,7 @@ impl<T: EthSpec> ExecutionLayer<T> {
attempts."
);
}
full_payload.into()
(full_payload.into(), block_value)
})
})
.await
Expand Down
11 changes: 7 additions & 4 deletions beacon_node/execution_layer/src/test_utils/mock_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ impl<E: EthSpec> mev_build_rs::BlindedBlockProvider for MockBuilder<E> {
finalized_hash: Some(finalized_execution_hash),
};

let payload = self
let (payload, block_value) = self
.el
.get_full_payload_caching::<BlindedPayload<E>>(
head_execution_hash,
Expand All @@ -314,8 +314,11 @@ impl<E: EthSpec> mev_build_rs::BlindedBlockProvider for MockBuilder<E> {
forkchoice_update_params,
)
.await
.map_err(convert_err)?
.to_execution_payload_header();
.map_err(convert_err)?;

let payload = payload.to_execution_payload_header();
let ssz_block_val =
block_value.map_or(ssz_rs::U256::default(), |val| to_ssz_rs(&val).unwrap());

let json_payload = serde_json::to_string(&payload).map_err(convert_err)?;
let mut header: ServerPayloadHeader =
Expand All @@ -325,7 +328,7 @@ impl<E: EthSpec> mev_build_rs::BlindedBlockProvider for MockBuilder<E> {

let mut message = BuilderBid {
header,
value: ssz_rs::U256::default(),
value: ssz_block_val,
public_key: self.builder_sk.public_key(),
};

Expand Down