Skip to content
Draft
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
28 changes: 26 additions & 2 deletions bindings/c/src/containers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ use execution_engine::{
BlobAndProofV1, BlobAndProofV2, BlobsBundleV1, BlobsBundleV2, EngineGetPayloadV2Response,
EngineGetPayloadV3Response, EngineGetPayloadV4Response, EngineGetPayloadV5Response,
ExecutionPayloadV1, ExecutionPayloadV2, ExecutionPayloadV3, ForkChoiceStateV1,
PayloadAttributesV1, PayloadAttributesV2, PayloadAttributesV3, PayloadStatusV1,
PayloadValidationStatus, RawExecutionRequests, RequestType, WithdrawalV1,
PayloadAttributesV1, PayloadAttributesV2, PayloadAttributesV3, PayloadAttributesV4,
PayloadStatusV1, PayloadValidationStatus, RawExecutionRequests, RequestType, WithdrawalV1,
};
use generic_array::ArrayLength;
use ssz::{ByteVector, ContiguousList, ContiguousVector, SszReadDefault, SszWrite};
Expand Down Expand Up @@ -407,6 +407,30 @@ impl From<PayloadAttributesV3<Mainnet>> for CPayloadAttributesV3 {
}
}

#[derive(Debug, Default)]
#[repr(C)]
pub struct CPayloadAttributesV4 {
timestamp: u64,
prev_randao: CH256,
suggested_fee_recipient: CH160,
withdrawals: CVec<CWithdrawalV1>,
parent_beacon_block_root: CH256,
slot_number: u64,
}

impl From<PayloadAttributesV4<Mainnet>> for CPayloadAttributesV4 {
fn from(value: PayloadAttributesV4<Mainnet>) -> Self {
Self {
timestamp: value.timestamp,
prev_randao: value.prev_randao.into(),
suggested_fee_recipient: value.suggested_fee_recipient.into(),
withdrawals: value.withdrawals.into_iter().map(Into::into).collect(),
parent_beacon_block_root: value.parent_beacon_block_root.into(),
slot_number: value.slot_number,
}
}
}

#[derive(Debug)]
#[repr(C)]
#[allow(unused, reason = "constructed from the C side of bindings")]
Expand Down
22 changes: 20 additions & 2 deletions bindings/c/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ use execution_engine::{
BlobAndProofV1, EngineGetPayloadV1Response, EngineGetPayloadV2Response,
EngineGetPayloadV3Response, EngineGetPayloadV4Response, EngineGetPayloadV5Response,
ExecutionPayloadV1, ExecutionPayloadV2, ExecutionPayloadV3, ForkChoiceStateV1,
PayloadAttributesV1, PayloadAttributesV2, PayloadAttributesV3, PayloadStatusV1,
PayloadAttributesV1, PayloadAttributesV2, PayloadAttributesV3, PayloadAttributesV4,
PayloadStatusV1,
};
use runtime::{grandine_args::GrandineArgs, run, shutdown};
use tracing::error;
Expand All @@ -28,7 +29,7 @@ use crate::{
CEngineGetPayloadV3Response, CEngineGetPayloadV4Response, CEngineGetPayloadV5Response,
CExecutionPayloadV1, CExecutionPayloadV2, CExecutionPayloadV3, CExecutionRequests,
CForkChoiceStateV1, CForkChoiceUpdatedResponse, CPayloadAttributesV1, CPayloadAttributesV2,
CPayloadAttributesV3, CPayloadStatusV1,
CPayloadAttributesV3, CPayloadAttributesV4, CPayloadStatusV1,
},
generic::{CGrandineString, COption, CResult, CVec, GRANDINE_ERROR_GENERIC},
layout::{CLayout, repeat_layout},
Expand Down Expand Up @@ -68,6 +69,10 @@ pub struct CEmbedAdapter {
state: CForkChoiceStateV1,
payload: COption<CPayloadAttributesV3>,
) -> CResult<CForkChoiceUpdatedResponse>,
engine_forkchoice_updated_v4: unsafe extern "C" fn(
state: CForkChoiceStateV1,
payload: COption<CPayloadAttributesV4>,
) -> CResult<CForkChoiceUpdatedResponse>,
engine_get_payload_v1: unsafe extern "C" fn(payload_id: CH64) -> CResult<CExecutionPayloadV1>,
engine_get_payload_v2:
unsafe extern "C" fn(payload_id: CH64) -> CResult<CEngineGetPayloadV2Response>,
Expand Down Expand Up @@ -214,6 +219,19 @@ impl eth1_api::EmbedAdapter for CEmbedAdapter {
Result::<_>::from(result).map(Into::into)
}

fn engine_forkchoice_updated_v4(
&self,
state: ForkChoiceStateV1,
payload: Option<PayloadAttributesV4<types::preset::Mainnet>>,
) -> Result<eth1_api::RawForkChoiceUpdatedResponse> {
let state: CForkChoiceStateV1 = state.into();
let payload: Option<CPayloadAttributesV4> = payload.map(Into::into);
let payload = payload.into();
let result = unsafe { (self.engine_forkchoice_updated_v4)(state, payload) };

Result::<_>::from(result).map(Into::into)
}

fn engine_get_payload_v1(
&self,
payload_id: web3::types::H64,
Expand Down
7 changes: 7 additions & 0 deletions bindings/csharp/Grandine.NethermindPlugin/GrandineClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate CResult_CForkChoiceUpdatedResponse EngineForkchoiceUpdatedV3Delegate(CForkChoiceStateV1 state, COption_CPayloadAttributesV3 attributes);

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate CResult_CForkChoiceUpdatedResponse EngineForkchoiceUpdatedV4Delegate(CForkChoiceStateV1 state, COption_CPayloadAttributesV4 attributes);

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate CResult_CExecutionPayloadV1 EngineGetPayloadV1Delegate(CH64 payloadId);

Expand Down Expand Up @@ -65,6 +68,7 @@ public class GrandineClient : IAsyncDisposable
private readonly EngineForkchoiceUpdatedV1Delegate engineForkchoiceUpdatedV1;
private readonly EngineForkchoiceUpdatedV2Delegate engineForkchoiceUpdatedV2;
private readonly EngineForkchoiceUpdatedV3Delegate engineForkchoiceUpdatedV3;
private readonly EngineForkchoiceUpdatedV4Delegate engineForkchoiceUpdatedV4;
private readonly EngineGetPayloadV1Delegate engineGetPayloadV1;
private readonly EngineGetPayloadV2Delegate engineGetPayloadV2;
private readonly EngineGetPayloadV3Delegate engineGetPayloadV3;
Expand Down Expand Up @@ -97,6 +101,7 @@ public GrandineClient(IGrandineEngineApi engineApi)
this.engineForkchoiceUpdatedV1 = this.engineApi.EngineForkchoiceUpdatedV1;
this.engineForkchoiceUpdatedV2 = this.engineApi.EngineForkchoiceUpdatedV2;
this.engineForkchoiceUpdatedV3 = this.engineApi.EngineForkchoiceUpdatedV3;
this.engineForkchoiceUpdatedV4 = this.engineApi.EngineForkchoiceUpdatedV4;
this.engineGetPayloadV1 = this.engineApi.EngineGetPayloadV1;
this.engineGetPayloadV2 = this.engineApi.EngineGetPayloadV2;
this.engineGetPayloadV3 = this.engineApi.EngineGetPayloadV3;
Expand All @@ -113,6 +118,7 @@ public GrandineClient(IGrandineEngineApi engineApi)
IntPtr engine_forkchoiceUpdatedV1Ptr = Marshal.GetFunctionPointerForDelegate(this.engineForkchoiceUpdatedV1);
IntPtr engine_forkchoiceUpdatedV2Ptr = Marshal.GetFunctionPointerForDelegate(this.engineForkchoiceUpdatedV2);
IntPtr engine_forkchoiceUpdatedV3Ptr = Marshal.GetFunctionPointerForDelegate(this.engineForkchoiceUpdatedV3);
IntPtr engine_forkchoiceUpdatedV4Ptr = Marshal.GetFunctionPointerForDelegate(this.engineForkchoiceUpdatedV4);
IntPtr engine_getPayloadV1Ptr = Marshal.GetFunctionPointerForDelegate(this.engineGetPayloadV1);
IntPtr engine_getPayloadV2Ptr = Marshal.GetFunctionPointerForDelegate(this.engineGetPayloadV2);
IntPtr engine_getPayloadV3Ptr = Marshal.GetFunctionPointerForDelegate(this.engineGetPayloadV3);
Expand All @@ -131,6 +137,7 @@ public GrandineClient(IGrandineEngineApi engineApi)
engine_forkchoice_updated_v1 = (delegate* unmanaged[Cdecl]<CForkChoiceStateV1, COption_CPayloadAttributesV1, CResult_CForkChoiceUpdatedResponse>)engine_forkchoiceUpdatedV1Ptr,
engine_forkchoice_updated_v2 = (delegate* unmanaged[Cdecl]<CForkChoiceStateV1, COption_CPayloadAttributesV2, CResult_CForkChoiceUpdatedResponse>)engine_forkchoiceUpdatedV2Ptr,
engine_forkchoice_updated_v3 = (delegate* unmanaged[Cdecl]<CForkChoiceStateV1, COption_CPayloadAttributesV3, CResult_CForkChoiceUpdatedResponse>)engine_forkchoiceUpdatedV3Ptr,
engine_forkchoice_updated_v4 = (delegate* unmanaged[Cdecl]<CForkChoiceStateV1, COption_CPayloadAttributesV4, CResult_CForkChoiceUpdatedResponse>)engine_forkchoiceUpdatedV4Ptr,
engine_get_payload_v1 = (delegate* unmanaged[Cdecl]<CH64, CResult_CExecutionPayloadV1>)engine_getPayloadV1Ptr,
engine_get_payload_v2 = (delegate* unmanaged[Cdecl]<CH64, CResult_CEngineGetPayloadV2Response>)engine_getPayloadV2Ptr,
engine_get_payload_v3 = (delegate* unmanaged[Cdecl]<CH64, CResult_CEngineGetPayloadV3Response>)engine_getPayloadV3Ptr,
Expand Down
21 changes: 21 additions & 0 deletions bindings/csharp/Grandine.NethermindPlugin/GrandineEngineApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,27 @@ public CResult_CForkChoiceUpdatedResponse EngineForkchoiceUpdatedV3(CForkChoiceS
}
}

public CResult_CForkChoiceUpdatedResponse EngineForkchoiceUpdatedV4(CForkChoiceStateV1 state, COption_CPayloadAttributesV4 payload)
{
this.logger.Debug("Received engine_forkchoiceUpdatedV4 request from grandine");

try
{
var forkchoiceUpdatedResult = this.engineRpc.engine_forkchoiceUpdatedV4(
state.ToForkchoiceStateV1(),
GrandineUtils.ConvertPayloadAttributes(payload)).Result;

return forkchoiceUpdatedResult.Result != Result.Success
? CResult_CForkChoiceUpdatedResponse.Fail(NativeMethods.GRANDINE_ERROR_ENGINE_API, forkchoiceUpdatedResult.Result.Error)
: CResult_CForkChoiceUpdatedResponse.Success(new CForkChoiceUpdatedResponse(forkchoiceUpdatedResult.Data));
}
catch (Exception e)
{
this.logger.Error("Unexpected exception occurred during engine_forkchoiceUpdatedV4 function invocation", e);
return CResult_CForkChoiceUpdatedResponse.Fail(NativeMethods.GRANDINE_ERROR_GENERIC, e.Message);
}
}

public CResult_CExecutionPayloadV1 EngineGetPayloadV1(CH64 payloadId)
{
this.logger.Debug("Received engine_getPayloadV1 request from grandine");
Expand Down
18 changes: 18 additions & 0 deletions bindings/csharp/Grandine.NethermindPlugin/GrandineUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,24 @@ public static CPayloadValidationStatus ConvertPayloadValidationStatus(string sta
};
}

public static PayloadAttributes? ConvertPayloadAttributes(COption_CPayloadAttributesV4 attr)
{
if (!attr.is_something)
{
return null;
}

return new PayloadAttributes
{
Timestamp = attr.value.timestamp,
PrevRandao = attr.value.prev_randao.ToHash256(),
SuggestedFeeRecipient = attr.value.suggested_fee_recipient.ToAddress(),
Withdrawals = WithdrawalsFromNative(attr.value.withdrawals),
ParentBeaconBlockRoot = attr.value.parent_beacon_block_root.ToHash256(),
SlotNumber = attr.value.slot_number,
};
}

public static IEnumerable<string> ConvertCapabilities(CVec_CGrandineString capabilities)
{
var span = capabilities.AsSpan();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ public interface IGrandineEngineApi

CResult_CForkChoiceUpdatedResponse EngineForkchoiceUpdatedV3(CForkChoiceStateV1 state, COption_CPayloadAttributesV3 payload);

CResult_CForkChoiceUpdatedResponse EngineForkchoiceUpdatedV4(CForkChoiceStateV1 state, COption_CPayloadAttributesV4 payload);

CResult_CExecutionPayloadV1 EngineGetPayloadV1(CH64 payloadId);

CResult_CEngineGetPayloadV2Response EngineGetPayloadV2(CH64 payloadId);
Expand Down
5 changes: 3 additions & 2 deletions block_producer/src/block_producer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use dedicated_executor::{DedicatedExecutor, Job};
use eth1_api::{ApiController, ClientVersions, Eth1ExecutionEngine, WithClientVersions};
use execution_engine::{
ExecutionEngine as _, PayloadAttributes, PayloadAttributesV1, PayloadAttributesV2,
PayloadAttributesV3, PayloadId,
PayloadAttributesV3, PayloadAttributesV4, PayloadId,
};
use features::Feature;
use fork_choice_control::Wait;
Expand Down Expand Up @@ -1627,12 +1627,13 @@ impl<P: Preset, W: Wait> BlockBuildContext<P, W> {
let parent_beacon_block_root =
accessors::get_block_root_at_slot(state, state.slot().saturating_sub(1))?;

PayloadAttributes::Gloas(PayloadAttributesV3 {
PayloadAttributes::Gloas(PayloadAttributesV4 {
timestamp,
prev_randao,
suggested_fee_recipient,
withdrawals,
parent_beacon_block_root,
slot_number: state.slot(),
})
}
};
Expand Down
54 changes: 40 additions & 14 deletions eth1_api/src/eth1_api/embed_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use execution_engine::{
EngineGetPayloadV3Response, EngineGetPayloadV4Response, EngineGetPayloadV5Response,
ExecutionPayloadV1, ExecutionPayloadV2, ExecutionPayloadV3, ForkChoiceStateV1,
ForkChoiceUpdatedResponse, PayloadAttributes, PayloadAttributesV1, PayloadAttributesV2,
PayloadAttributesV3, PayloadId, PayloadStatusV1,
PayloadAttributesV3, PayloadAttributesV4, PayloadId, PayloadStatusV1,
};
use futures::channel::mpsc::UnboundedSender;
use prometheus_metrics::Metrics;
Expand Down Expand Up @@ -41,9 +41,10 @@ use crate::{
deposit_event::DepositEvent,
eth1_api::{
ENGINE_FORKCHOICE_UPDATED_V1, ENGINE_FORKCHOICE_UPDATED_V2, ENGINE_FORKCHOICE_UPDATED_V3,
ENGINE_GET_EL_BLOBS_V1, ENGINE_GET_EL_BLOBS_V2, ENGINE_GET_PAYLOAD_V1,
ENGINE_GET_PAYLOAD_V2, ENGINE_GET_PAYLOAD_V3, ENGINE_GET_PAYLOAD_V4, ENGINE_GET_PAYLOAD_V5,
ENGINE_NEW_PAYLOAD_V1, ENGINE_NEW_PAYLOAD_V2, ENGINE_NEW_PAYLOAD_V3, ENGINE_NEW_PAYLOAD_V4,
ENGINE_FORKCHOICE_UPDATED_V4, ENGINE_GET_EL_BLOBS_V1, ENGINE_GET_EL_BLOBS_V2,
ENGINE_GET_PAYLOAD_V1, ENGINE_GET_PAYLOAD_V2, ENGINE_GET_PAYLOAD_V3, ENGINE_GET_PAYLOAD_V4,
ENGINE_GET_PAYLOAD_V5, ENGINE_NEW_PAYLOAD_V1, ENGINE_NEW_PAYLOAD_V2, ENGINE_NEW_PAYLOAD_V3,
ENGINE_NEW_PAYLOAD_V4,
},
eth1_block::Eth1Block,
};
Expand Down Expand Up @@ -98,6 +99,11 @@ pub trait EmbedAdapter: Send + Sync {
state: ForkChoiceStateV1,
payload: Option<PayloadAttributesV3<Mainnet>>,
) -> Result<RawForkChoiceUpdatedResponse>;
fn engine_forkchoice_updated_v4(
&self,
state: ForkChoiceStateV1,
payload: Option<PayloadAttributesV4<Mainnet>>,
) -> Result<RawForkChoiceUpdatedResponse>;

fn engine_get_payload_v1(&self, payload_id: H64)
-> Result<EngineGetPayloadV1Response<Mainnet>>;
Expand Down Expand Up @@ -451,14 +457,15 @@ impl Eth1Api {
}
}

/// Calls [`engine_forkchoiceUpdatedV1`] or [`engine_forkchoiceUpdatedV2`] or [`engine_forkchoiceUpdatedV3`] depending on `payload_attributes`.
/// Calls [`engine_forkchoiceUpdatedV1`] or [`engine_forkchoiceUpdatedV2`] or [`engine_forkchoiceUpdatedV3`] or [`engine_forkchoiceUpdatedV4`] depending on `payload_attributes`.
///
/// Later versions of `engine_forkchoiceUpdated` accept parameters of all prior versions,
/// but using the earlier versions allows the application to work with old execution clients.
///
/// [`engine_forkchoiceUpdatedV1`]: https://github.com/ethereum/execution-apis/blob/b7c5d3420e00648f456744d121ffbd929862924d/src/engine/paris.md#engine_forkchoiceupdatedv1
/// [`engine_forkchoiceUpdatedV2`]: https://github.com/ethereum/execution-apis/blob/b7c5d3420e00648f456744d121ffbd929862924d/src/engine/shanghai.md#engine_forkchoiceupdatedv2
/// [`engine_forkchoiceUpdatedV3`]: https://github.com/ethereum/execution-apis/blob/a0d03086564ab1838b462befbc083f873dcf0c0f/src/engine/cancun.md#engine_forkchoiceupdatedv3
/// [`engine_forkchoiceUpdatedV4`]: https://github.com/ethereum/execution-apis/blob/ffe6c839567f931ece3276d8242963744f09bf67/src/engine/amsterdam.md#engine_forkchoiceupdatedv4
pub async fn forkchoice_updated<P: Preset>(
&self,
head_block_hash: ExecutionBlockHash,
Expand Down Expand Up @@ -507,8 +514,7 @@ impl Eth1Api {
Err(Error::InvalidParameters)
}
})
.transpose()?
.clone();
.transpose()?;

self.exec(move |adapter| {
adapter.engine_forkchoice_updated_v1(fork_choice_state, payload_attributes)
Expand All @@ -531,15 +537,14 @@ impl Eth1Api {
Err(Error::InvalidParameters)
}
})
.transpose()?
.clone();
.transpose()?;

self.exec(move |adapter| {
adapter.engine_forkchoice_updated_v2(fork_choice_state, payload_attributes)
})
.await?
}
Phase::Deneb | Phase::Electra | Phase::Fulu | Phase::Gloas => {
Phase::Deneb | Phase::Electra | Phase::Fulu => {
let _timer = self.metrics.as_ref().map(|metrics| {
prometheus_metrics::start_timer_vec(
&metrics.eth1_api_request_times,
Expand All @@ -551,22 +556,43 @@ impl Eth1Api {
.map(|value| {
if let PayloadAttributes::Deneb(value)
| PayloadAttributes::Electra(value)
| PayloadAttributes::Fulu(value)
| PayloadAttributes::Gloas(value) = value
| PayloadAttributes::Fulu(value) = value
{
Ok(value)
} else {
Err(Error::InvalidParameters)
}
})
.transpose()?
.clone();
.transpose()?;

self.exec(move |adapter| {
adapter.engine_forkchoice_updated_v3(fork_choice_state, payload_attributes)
})
.await?
}
Phase::Gloas => {
let _timer = self.metrics.as_ref().map(|metrics| {
prometheus_metrics::start_timer_vec(
&metrics.eth1_api_request_times,
ENGINE_FORKCHOICE_UPDATED_V4,
)
});

let payload_attributes = payload_attributes
.map(|value| {
if let PayloadAttributes::Gloas(value) = value {
Ok(value)
} else {
Err(Error::InvalidParameters)
}
})
.transpose()?;

self.exec(move |adapter| {
adapter.engine_forkchoice_updated_v4(fork_choice_state, payload_attributes)
})
.await?
}
_ => {
// This match arm will silently match any new phases.
// Cause a compilation error if a new phase is added.
Expand Down
Loading
Loading