Rpc: add support for minimum context slot to `getBlocks(WithLimit)` endpoints (#191)

* Support min_context_slot field in getBlocksWithLimit input

* Use min_context_slot in get_blocks_with_limit

* Support min_context_slot field in getBlocks input

* Use min_context_slot in get_blocks
This commit is contained in:
Tyera 2024-03-11 23:59:18 -06:00 committed by GHA: Update Upstream From Fork
parent 8b927561dc
commit 814181b07b
2 changed files with 87 additions and 51 deletions

View File

@ -321,14 +321,14 @@ impl EncodingConfig for RpcTransactionConfig {
#[serde(untagged)]
pub enum RpcBlocksConfigWrapper {
EndSlotOnly(Option<Slot>),
CommitmentOnly(Option<CommitmentConfig>),
ConfigOnly(Option<RpcContextConfig>),
}
impl RpcBlocksConfigWrapper {
pub fn unzip(&self) -> (Option<Slot>, Option<CommitmentConfig>) {
pub fn unzip(&self) -> (Option<Slot>, Option<RpcContextConfig>) {
match &self {
RpcBlocksConfigWrapper::EndSlotOnly(end_slot) => (*end_slot, None),
RpcBlocksConfigWrapper::CommitmentOnly(commitment) => (None, *commitment),
RpcBlocksConfigWrapper::ConfigOnly(config) => (None, *config),
}
}
}

View File

@ -527,13 +527,14 @@ impl JsonRpcRequestProcessor {
let config = config.unwrap_or_default();
let epoch_schedule = self.get_epoch_schedule();
let first_available_block = self.get_first_available_block().await;
let context_config = RpcContextConfig {
commitment: config.commitment,
min_context_slot: config.min_context_slot,
};
let epoch = match config.epoch {
Some(epoch) => epoch,
None => epoch_schedule
.get_epoch(self.get_slot(RpcContextConfig {
commitment: config.commitment,
min_context_slot: config.min_context_slot,
})?)
.get_epoch(self.get_slot(context_config)?)
.saturating_sub(1),
};
@ -555,7 +556,7 @@ impl JsonRpcRequestProcessor {
}
let first_confirmed_block_in_epoch = *self
.get_blocks_with_limit(first_slot_in_epoch, 1, config.commitment)
.get_blocks_with_limit(first_slot_in_epoch, 1, Some(context_config))
.await?
.first()
.ok_or(RpcCustomError::BlockNotAvailable {
@ -1170,9 +1171,10 @@ impl JsonRpcRequestProcessor {
&self,
start_slot: Slot,
end_slot: Option<Slot>,
commitment: Option<CommitmentConfig>,
config: Option<RpcContextConfig>,
) -> Result<Vec<Slot>> {
let commitment = commitment.unwrap_or_default();
let config = config.unwrap_or_default();
let commitment = config.commitment.unwrap_or_default();
check_is_at_least_confirmed(commitment)?;
let highest_super_majority_root = self
@ -1181,12 +1183,20 @@ impl JsonRpcRequestProcessor {
.unwrap()
.highest_super_majority_root();
let min_context_slot = config.min_context_slot.unwrap_or_default();
if commitment.is_finalized() && highest_super_majority_root < min_context_slot {
return Err(RpcCustomError::MinContextSlotNotReached {
context_slot: highest_super_majority_root,
}
.into());
}
let end_slot = min(
end_slot.unwrap_or_else(|| start_slot.saturating_add(MAX_GET_CONFIRMED_BLOCKS_RANGE)),
if commitment.is_finalized() {
highest_super_majority_root
} else {
self.bank(Some(CommitmentConfig::confirmed())).slot()
self.get_bank_with_config(config)?.slot()
},
);
if end_slot < start_slot {
@ -1236,14 +1246,16 @@ impl JsonRpcRequestProcessor {
.unwrap_or_else(|| start_slot.saturating_sub(1));
// Maybe add confirmed blocks
if commitment.is_confirmed() && last_element < end_slot {
let confirmed_bank = self.bank(Some(CommitmentConfig::confirmed()));
let mut confirmed_blocks = confirmed_bank
.status_cache_ancestors()
.into_iter()
.filter(|&slot| slot <= end_slot && slot > last_element)
.collect();
blocks.append(&mut confirmed_blocks);
if commitment.is_confirmed() {
let confirmed_bank = self.get_bank_with_config(config)?;
if last_element < end_slot {
let mut confirmed_blocks = confirmed_bank
.status_cache_ancestors()
.into_iter()
.filter(|&slot| slot <= end_slot && slot > last_element)
.collect();
blocks.append(&mut confirmed_blocks);
}
}
Ok(blocks)
@ -1253,9 +1265,10 @@ impl JsonRpcRequestProcessor {
&self,
start_slot: Slot,
limit: usize,
commitment: Option<CommitmentConfig>,
config: Option<RpcContextConfig>,
) -> Result<Vec<Slot>> {
let commitment = commitment.unwrap_or_default();
let config = config.unwrap_or_default();
let commitment = config.commitment.unwrap_or_default();
check_is_at_least_confirmed(commitment)?;
if limit > MAX_GET_CONFIRMED_BLOCKS_RANGE as usize {
@ -1287,6 +1300,16 @@ impl JsonRpcRequestProcessor {
.unwrap()
.highest_super_majority_root();
if commitment.is_finalized() {
let min_context_slot = config.min_context_slot.unwrap_or_default();
if highest_super_majority_root < min_context_slot {
return Err(RpcCustomError::MinContextSlotNotReached {
context_slot: highest_super_majority_root,
}
.into());
}
}
// Finalized blocks
let mut blocks: Vec<_> = self
.blockstore
@ -1297,19 +1320,21 @@ impl JsonRpcRequestProcessor {
.collect();
// Maybe add confirmed blocks
if commitment.is_confirmed() && blocks.len() < limit {
let last_element = blocks
.last()
.cloned()
.unwrap_or_else(|| start_slot.saturating_sub(1));
let confirmed_bank = self.bank(Some(CommitmentConfig::confirmed()));
let mut confirmed_blocks = confirmed_bank
.status_cache_ancestors()
.into_iter()
.filter(|&slot| slot > last_element)
.collect();
blocks.append(&mut confirmed_blocks);
blocks.truncate(limit);
if commitment.is_confirmed() {
let confirmed_bank = self.get_bank_with_config(config)?;
if blocks.len() < limit {
let last_element = blocks
.last()
.cloned()
.unwrap_or_else(|| start_slot.saturating_sub(1));
let mut confirmed_blocks = confirmed_bank
.status_cache_ancestors()
.into_iter()
.filter(|&slot| slot > last_element)
.collect();
blocks.append(&mut confirmed_blocks);
blocks.truncate(limit);
}
}
Ok(blocks)
@ -3339,8 +3364,8 @@ pub mod rpc_full {
&self,
meta: Self::Metadata,
start_slot: Slot,
config: Option<RpcBlocksConfigWrapper>,
commitment: Option<CommitmentConfig>,
wrapper: Option<RpcBlocksConfigWrapper>,
config: Option<RpcContextConfig>,
) -> BoxFuture<Result<Vec<Slot>>>;
#[rpc(meta, name = "getBlocksWithLimit")]
@ -3349,7 +3374,7 @@ pub mod rpc_full {
meta: Self::Metadata,
start_slot: Slot,
limit: usize,
commitment: Option<CommitmentConfig>,
config: Option<RpcContextConfig>,
) -> BoxFuture<Result<Vec<Slot>>>;
#[rpc(meta, name = "getTransaction")]
@ -3841,17 +3866,17 @@ pub mod rpc_full {
&self,
meta: Self::Metadata,
start_slot: Slot,
config: Option<RpcBlocksConfigWrapper>,
commitment: Option<CommitmentConfig>,
wrapper: Option<RpcBlocksConfigWrapper>,
config: Option<RpcContextConfig>,
) -> BoxFuture<Result<Vec<Slot>>> {
let (end_slot, maybe_commitment) =
config.map(|config| config.unzip()).unwrap_or_default();
let (end_slot, maybe_config) =
wrapper.map(|wrapper| wrapper.unzip()).unwrap_or_default();
debug!(
"get_blocks rpc request received: {}-{:?}",
start_slot, end_slot
);
Box::pin(async move {
meta.get_blocks(start_slot, end_slot, commitment.or(maybe_commitment))
meta.get_blocks(start_slot, end_slot, config.or(maybe_config))
.await
})
}
@ -3861,16 +3886,13 @@ pub mod rpc_full {
meta: Self::Metadata,
start_slot: Slot,
limit: usize,
commitment: Option<CommitmentConfig>,
config: Option<RpcContextConfig>,
) -> BoxFuture<Result<Vec<Slot>>> {
debug!(
"get_blocks_with_limit rpc request received: {}-{}",
start_slot, limit,
);
Box::pin(async move {
meta.get_blocks_with_limit(start_slot, limit, commitment)
.await
})
Box::pin(async move { meta.get_blocks_with_limit(start_slot, limit, config).await })
}
fn get_block_time(
@ -4282,8 +4304,15 @@ pub mod rpc_deprecated_v1_7 {
start_slot, end_slot
);
Box::pin(async move {
meta.get_blocks(start_slot, end_slot, commitment.or(maybe_commitment))
.await
meta.get_blocks(
start_slot,
end_slot,
Some(RpcContextConfig {
commitment: commitment.or(maybe_commitment),
min_context_slot: None,
}),
)
.await
})
}
@ -4299,8 +4328,15 @@ pub mod rpc_deprecated_v1_7 {
start_slot, limit,
);
Box::pin(async move {
meta.get_blocks_with_limit(start_slot, limit, commitment)
.await
meta.get_blocks_with_limit(
start_slot,
limit,
Some(RpcContextConfig {
commitment,
min_context_slot: None,
}),
)
.await
})
}