use super::{PayloadStatus, PayloadStatusEnum};
use crate::PayloadId;
use alloy_primitives::B256;
use serde::{Deserialize, Serialize};
pub const INVALID_FORK_CHOICE_STATE_ERROR: i32 = -38002;
pub const INVALID_PAYLOAD_ATTRIBUTES_ERROR: i32 = -38003;
pub const INVALID_FORK_CHOICE_STATE_ERROR_MSG: &str = "Invalid forkchoice state";
pub const INVALID_PAYLOAD_ATTRIBUTES_ERROR_MSG: &str = "Invalid payload attributes";
pub type ForkChoiceUpdateResult = Result<ForkchoiceUpdated, ForkchoiceUpdateError>;
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ForkchoiceState {
pub head_block_hash: B256,
pub safe_block_hash: B256,
pub finalized_block_hash: B256,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, thiserror::Error)]
pub enum ForkchoiceUpdateError {
#[error("invalid payload attributes")]
UpdatedInvalidPayloadAttributes,
#[error("invalid forkchoice state")]
InvalidState,
#[error("final block not available in database")]
UnknownFinalBlock,
}
#[cfg(feature = "jsonrpsee-types")]
impl From<ForkchoiceUpdateError> for jsonrpsee_types::error::ErrorObject<'static> {
fn from(value: ForkchoiceUpdateError) -> Self {
match value {
ForkchoiceUpdateError::UpdatedInvalidPayloadAttributes => {
jsonrpsee_types::error::ErrorObject::owned(
INVALID_PAYLOAD_ATTRIBUTES_ERROR,
INVALID_PAYLOAD_ATTRIBUTES_ERROR_MSG,
None::<()>,
)
}
ForkchoiceUpdateError::InvalidState => jsonrpsee_types::error::ErrorObject::owned(
INVALID_FORK_CHOICE_STATE_ERROR,
INVALID_FORK_CHOICE_STATE_ERROR_MSG,
None::<()>,
),
ForkchoiceUpdateError::UnknownFinalBlock => jsonrpsee_types::error::ErrorObject::owned(
INVALID_FORK_CHOICE_STATE_ERROR,
INVALID_FORK_CHOICE_STATE_ERROR_MSG,
None::<()>,
),
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ForkchoiceUpdated {
pub payload_status: PayloadStatus,
pub payload_id: Option<PayloadId>,
}
impl ForkchoiceUpdated {
pub const fn new(payload_status: PayloadStatus) -> Self {
Self { payload_status, payload_id: None }
}
pub const fn from_status(status: PayloadStatusEnum) -> Self {
Self { payload_status: PayloadStatus::from_status(status), payload_id: None }
}
pub const fn with_latest_valid_hash(mut self, hash: B256) -> Self {
self.payload_status.latest_valid_hash = Some(hash);
self
}
pub const fn with_payload_id(mut self, id: PayloadId) -> Self {
self.payload_id = Some(id);
self
}
pub const fn is_syncing(&self) -> bool {
self.payload_status.is_syncing()
}
pub const fn is_valid(&self) -> bool {
self.payload_status.is_valid()
}
pub const fn is_invalid(&self) -> bool {
self.payload_status.is_invalid()
}
}