Skip to content
Merged
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
8 changes: 8 additions & 0 deletions finalizer/src/actor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -970,6 +970,14 @@ impl<
let length = self.canonical_state.get_epocher().current_length();
let _ = sender.send(ConsensusStateResponse::EpochLength(length));
}
ConsensusStateRequest::GetEpochBounds(epoch) => {
let bounds = self
.canonical_state
.get_epocher()
.epoch_bounds(Epoch::new(epoch))
.map(|(first, last)| (first.get(), last.get()));
let _ = sender.send(ConsensusStateResponse::EpochBounds(bounds));
}
ConsensusStateRequest::GetDeposit(index) => {
let deposit = self.canonical_state.get_deposit(index).cloned();
let _ = sender.send(ConsensusStateResponse::Deposit(deposit));
Expand Down
18 changes: 18 additions & 0 deletions finalizer/src/ingress.rs
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,24 @@ impl<S: Scheme<B::Digest>, B: ConsensusBlock> FinalizerMailbox<S, B> {
length
}

pub async fn get_epoch_bounds(&self, epoch: u64) -> Option<(u64, u64)> {
let (response, rx) = oneshot::channel();
let request = ConsensusStateRequest::GetEpochBounds(epoch);
let _ = self
.sender
.clone()
.send(FinalizerMessage::QueryState { request, response })
.await;

let res = rx
.await
.expect("consensus state query response sender dropped");
let ConsensusStateResponse::EpochBounds(bounds) = res else {
unreachable!("request and response variants must match");
};
bounds
}

pub async fn get_deposit(
&self,
index: usize,
Expand Down
7 changes: 5 additions & 2 deletions rpc/src/api.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::types::{
CheckpointInfoRes, CheckpointRes, DepositResponse, DepositTransactionResponse,
FinalizedHeaderRes, PendingWithdrawalResponse, PublicKeysResponse, StateProofResponse,
StateRootResponse, ValidatorAccountResponse,
EpochBoundsResponse, FinalizedHeaderRes, PendingWithdrawalResponse, PublicKeysResponse,
StateProofResponse, StateRootResponse, ValidatorAccountResponse,
};
use jsonrpsee::core::RpcResult;
use jsonrpsee::proc_macros::rpc;
Expand Down Expand Up @@ -57,6 +57,9 @@ pub trait SummitApi {
#[method(name = "getEpochLength")]
async fn get_epoch_length(&self) -> RpcResult<u64>;

#[method(name = "getEpochBounds")]
async fn get_epoch_bounds(&self, epoch: u64) -> RpcResult<EpochBoundsResponse>;

#[method(name = "getDeposit")]
async fn get_deposit(&self, index: usize) -> RpcResult<DepositResponse>;

Expand Down
2 changes: 2 additions & 0 deletions rpc/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ pub enum RpcError {
ValidatorNotFound,
DepositNotFound,
WithdrawalNotFound,
EpochNotFound,
InvalidPublicKey(String),
GenesisPathError(String),
IoError(String),
Expand All @@ -26,6 +27,7 @@ impl From<RpcError> for ErrorObjectOwned {
RpcError::FinalizedHeaderNotFound => {
ErrorObjectOwned::owned(2003, "Finalized header not found", None::<()>)
}
RpcError::EpochNotFound => ErrorObjectOwned::owned(2004, "Epoch not found", None::<()>),
RpcError::ValidatorNotFound => {
ErrorObjectOwned::owned(3000, "Validator not found", None::<()>)
}
Expand Down
15 changes: 13 additions & 2 deletions rpc/src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ use crate::api::{SummitApiServer, SummitProofApiServer};
use crate::error::RpcError;
use crate::types::{
CheckpointInfoRes, CheckpointRes, DepositResponse, DepositTransactionResponse,
FinalizedHeaderRes, PendingWithdrawalResponse, PublicKeysResponse, StateProofResponse,
StateRootResponse, ValidatorAccountResponse,
EpochBoundsResponse, FinalizedHeaderRes, PendingWithdrawalResponse, PublicKeysResponse,
StateProofResponse, StateRootResponse, ValidatorAccountResponse,
};
use alloy_primitives::{Address, U256, hex::FromHex as _};
use async_trait::async_trait;
Expand Down Expand Up @@ -289,6 +289,17 @@ impl SummitApiServer for SummitRpcServer {
Ok(epoch_length)
}

async fn get_epoch_bounds(&self, epoch: u64) -> RpcResult<EpochBoundsResponse> {
let bounds = self.finalizer_mailbox.get_epoch_bounds(epoch).await;
match bounds {
Some((first_height, last_height)) => Ok(EpochBoundsResponse {
first_height,
last_height,
}),
None => Err(RpcError::EpochNotFound.into()),
}
}

async fn get_deposit(&self, index: usize) -> RpcResult<DepositResponse> {
let deposit = self.finalizer_mailbox.get_deposit(index).await;
match deposit {
Expand Down
2 changes: 1 addition & 1 deletion rpc/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@ pub struct DepositTransactionResponse {
}

pub use summit_types::rpc::{
CheckpointInfoRes, CheckpointRes, DepositResponse, FinalizedHeaderRes,
CheckpointInfoRes, CheckpointRes, DepositResponse, EpochBoundsResponse, FinalizedHeaderRes,
PendingWithdrawalResponse, StateProofResponse, StateRootResponse, ValidatorAccountResponse,
};
6 changes: 6 additions & 0 deletions rpc/tests/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,12 @@ pub fn create_test_finalizer_mailbox(
ConsensusStateRequest::GetEpochLength => {
let _ = response.send(ConsensusStateResponse::EpochLength(10));
}
ConsensusStateRequest::GetEpochBounds(epoch) => {
let first = epoch * 10;
let last = first + 9;
let _ =
response.send(ConsensusStateResponse::EpochBounds(Some((first, last))));
}
},
_ => {}
}
Expand Down
16 changes: 16 additions & 0 deletions types/src/consensus_state_query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ pub enum ConsensusStateRequest {
GetMinimumStake,
GetMaximumStake,
GetEpochLength,
GetEpochBounds(u64),
GetDeposit(usize),
GetDepositCount,
GetWithdrawal([u8; 32]),
Expand All @@ -39,6 +40,7 @@ pub enum ConsensusStateResponse<S: Scheme> {
MinimumStake(u64),
MaximumStake(u64),
EpochLength(u64),
EpochBounds(Option<(u64, u64)>),
Deposit(Option<DepositRequest>),
DepositCount(usize),
Withdrawal(Option<PendingWithdrawal>),
Expand Down Expand Up @@ -218,4 +220,18 @@ impl<S: Scheme> ConsensusStateQuery<S> {
};
length
}

pub async fn get_epoch_bounds(&self, epoch: u64) -> Option<(u64, u64)> {
let (tx, rx) = oneshot::channel();
let req = ConsensusStateRequest::GetEpochBounds(epoch);
let _ = self.sender.clone().send((req, tx)).await;

let res = rx
.await
.expect("consensus state query response sender dropped");
let ConsensusStateResponse::EpochBounds(bounds) = res else {
unreachable!("request and response variants must match");
};
bounds
}
}
10 changes: 10 additions & 0 deletions types/src/dynamic_epocher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,16 @@ impl DynamicEpocher {
inner.current_epoch = epoch;
}

/// Returns the bounds (first height, last height) of a given epoch,
/// or `None` if the epoch is beyond `current_epoch + 1`.
pub fn epoch_bounds(&self, epoch: Epoch) -> Option<(Height, Height)> {
let inner = self.inner.read().unwrap();
if epoch.get() > inner.current_epoch.get() + 1 {
return None;
}
Self::bounds(&inner.segments, epoch)
}

/// Registers a new epoch length, taking effect at `current_epoch + 2`.
///
/// Returns an error if the target epoch is before the latest registered
Expand Down
6 changes: 6 additions & 0 deletions types/src/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,9 @@ pub struct StateProofResponse {
pub el_block_number: u64,
pub proofs: Vec<crate::ssz_state_tree::SszProof>,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct EpochBoundsResponse {
pub first_height: u64,
pub last_height: u64,
}
Loading