use super::{PayloadStatus, PayloadStatusEnum};
use crate::PayloadId;
use alloy_primitives::B256;
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)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
pub struct ForkchoiceState {
pub head_block_hash: B256,
pub safe_block_hash: B256,
pub finalized_block_hash: B256,
}
impl ForkchoiceState {
pub const fn same_hash(hash: B256) -> Self {
Self { head_block_hash: hash, safe_block_hash: hash, finalized_block_hash: hash }
}
#[inline]
pub fn state_head_hash(&self) -> Option<B256> {
if self.head_block_hash.is_zero() {
None
} else {
Some(self.head_block_hash)
}
}
#[inline]
pub fn state_safe_hash(&self) -> Option<B256> {
if self.safe_block_hash.is_zero() {
None
} else {
Some(self.safe_block_hash)
}
}
#[inline]
pub fn state_finalized_hash(&self) -> Option<B256> {
if self.finalized_block_hash.is_zero() {
None
} else {
Some(self.finalized_block_hash)
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, derive_more::Display)]
pub enum ForkchoiceUpdateError {
#[display("invalid payload attributes")]
UpdatedInvalidPayloadAttributes,
#[display("invalid forkchoice state")]
InvalidState,
#[display("final block not available in database")]
UnknownFinalBlock,
}
impl core::error::Error for ForkchoiceUpdateError {}
#[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 | ForkchoiceUpdateError::UnknownFinalBlock => {
jsonrpsee_types::error::ErrorObject::owned(
INVALID_FORK_CHOICE_STATE_ERROR,
INVALID_FORK_CHOICE_STATE_ERROR_MSG,
None::<()>,
)
}
}
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", 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()
}
}