v0.2.9-pre.009

This commit is contained in:
2026-08-24 17:26:27 +02:00
parent 433e69272a
commit a9fb6a7ac8
12 changed files with 1498 additions and 101 deletions

View File

@@ -1,11 +1,8 @@
// file: crates/ksp-onchain-transport-lib/src/grpc_subscribe.rs
// version: 6
// version: 7
#[cfg(test)]
const MAX_GRPC_BLOCKHASH_TEXT_LENGTH_BYTES: usize = 128;
#[cfg(test)]
const MAX_GRPC_BLOCK_VECTOR_COUNT: usize = 65_536;
#[cfg(test)]
const MAX_GRPC_SUBSCRIBE_ACCOUNT_DATA_LENGTH_BYTES: usize = 512 * 1024 * 1024;
const MAX_GRPC_SUBSCRIBE_ACCOUNT_PREDICATE_COUNT: usize = 256;
const MAX_GRPC_SUBSCRIBE_ACCOUNT_SELECTOR_COUNT: usize = 50_000;
@@ -16,26 +13,16 @@ const MAX_GRPC_SUBSCRIBE_FILTER_GROUP_COUNT: usize = 1_024;
const MAX_GRPC_SUBSCRIBE_FILTER_NAME_LENGTH_BYTES: usize = 128;
const MAX_GRPC_SUBSCRIBE_MEMCMP_BYTES: usize = 1024 * 1024;
const MAX_GRPC_SUBSCRIBE_MEMCMP_TEXT_LENGTH_BYTES: usize = 2 * 1024 * 1024;
#[cfg(test)]
const MAX_GRPC_SUBSCRIBE_SLOT_DEAD_ERROR_LENGTH_BYTES: usize = 16 * 1024;
const MAX_GRPC_SUBSCRIBE_TRANSACTION_SIGNATURE_TEXT_LENGTH_BYTES: usize = 128;
#[cfg(test)]
const MAX_GRPC_SUBSCRIBE_UPDATE_FILTER_COUNT: usize = 1_024;
#[cfg(test)]
const MAX_GRPC_TRANSACTION_ERROR_BYTES: usize = 64 * 1024;
#[cfg(test)]
const MAX_GRPC_TRANSACTION_INSTRUCTION_DATA_BYTES: usize = 1024 * 1024;
#[cfg(test)]
const MAX_GRPC_TRANSACTION_LOG_COUNT: usize = 16_384;
#[cfg(test)]
const MAX_GRPC_TRANSACTION_LOG_LENGTH_BYTES: usize = 64 * 1024;
#[cfg(test)]
const MAX_GRPC_TRANSACTION_RETURN_DATA_BYTES: usize = 1024 * 1024;
#[cfg(test)]
const MAX_GRPC_TRANSACTION_TEXT_LENGTH_BYTES: usize = 64 * 1024;
#[cfg(test)]
const MAX_GRPC_TRANSACTION_VECTOR_COUNT: usize = 65_536;
#[cfg(test)]
const YELLOWSTONE_HASH_LENGTH_BYTES: usize = 32;
const YELLOWSTONE_TRANSACTION_SIGNATURE_WIRE_LENGTH_BYTES: usize = 64;
@@ -105,7 +92,6 @@ impl YellowstoneAccountsDataSlice {
return self.length;
}
#[cfg(test)]
fn to_wire(self) -> yellowstone_grpc_proto::geyser::SubscribeRequestAccountsDataSlice {
return yellowstone_grpc_proto::geyser::SubscribeRequestAccountsDataSlice { offset: self.offset, length: self.length };
}
@@ -130,7 +116,6 @@ impl YellowstoneSubscribePing {
return self.id;
}
#[cfg(test)]
fn to_wire(self) -> yellowstone_grpc_proto::geyser::SubscribeRequestPing {
return yellowstone_grpc_proto::geyser::SubscribeRequestPing { id: self.id };
}
@@ -144,7 +129,6 @@ pub enum YellowstoneCuckooHashAlgorithm {
}
impl YellowstoneCuckooHashAlgorithm {
#[cfg(test)]
const fn to_wire(self) -> i32 {
return match self {
Self::SipHash => yellowstone_grpc_proto::geyser::CuckooHashAlgorithm::SipHash as i32,
@@ -222,7 +206,6 @@ impl YellowstoneCuckooFilter {
return self.hash_algorithm;
}
#[cfg(test)]
fn to_wire(&self) -> yellowstone_grpc_proto::geyser::CuckooFilter {
return yellowstone_grpc_proto::geyser::CuckooFilter {
data: self.data.clone(),
@@ -335,7 +318,6 @@ impl YellowstoneAccountMemcmp {
};
}
#[cfg(test)]
fn to_wire(&self) -> yellowstone_grpc_proto::geyser::SubscribeRequestFilterAccountsFilterMemcmp {
let data = match &self.data {
YellowstoneAccountMemcmpData::Bytes(value) => {
@@ -394,7 +376,6 @@ pub enum YellowstoneAccountFilterPredicate {
}
impl YellowstoneAccountFilterPredicate {
#[cfg(test)]
fn to_wire(&self) -> yellowstone_grpc_proto::geyser::SubscribeRequestFilterAccountsFilter {
let filter = match self {
Self::Memcmp(value) => yellowstone_grpc_proto::geyser::subscribe_request_filter_accounts_filter::Filter::Memcmp(value.to_wire()),
@@ -514,7 +495,6 @@ impl YellowstoneSubscribeAccountFilter {
return self.cuckoo_accounts_filter.as_ref();
}
#[cfg(test)]
fn to_wire(&self) -> yellowstone_grpc_proto::geyser::SubscribeRequestFilterAccounts {
return yellowstone_grpc_proto::geyser::SubscribeRequestFilterAccounts {
account: self.accounts.iter().map(std::string::ToString::to_string).collect(),
@@ -581,7 +561,6 @@ impl YellowstoneSubscribeSlotFilter {
return self.interslot_updates;
}
#[cfg(test)]
fn to_wire(self) -> yellowstone_grpc_proto::geyser::SubscribeRequestFilterSlots {
return yellowstone_grpc_proto::geyser::SubscribeRequestFilterSlots {
filter_by_commitment: self.filter_by_commitment,
@@ -872,7 +851,6 @@ pub enum YellowstoneTokenAccountExpansion {
}
impl YellowstoneTokenAccountExpansion {
#[cfg(test)]
const fn to_wire(self) -> i32 {
return match self {
Self::All => yellowstone_grpc_proto::geyser::TokenAccountExpansionControlFlag::All as i32,
@@ -1033,7 +1011,6 @@ impl YellowstoneSubscribeTransactionFilter {
return self.token_accounts;
}
#[cfg(test)]
fn to_wire(&self) -> yellowstone_grpc_proto::geyser::SubscribeRequestFilterTransactions {
return yellowstone_grpc_proto::geyser::SubscribeRequestFilterTransactions {
vote: self.vote,
@@ -2027,7 +2004,6 @@ impl YellowstoneSubscribeBlockFilter {
return self.cuckoo_account_include.as_ref();
}
#[cfg(test)]
fn to_wire(&self) -> yellowstone_grpc_proto::geyser::SubscribeRequestFilterBlocks {
return yellowstone_grpc_proto::geyser::SubscribeRequestFilterBlocks {
account_include: self.account_include.iter().map(std::string::ToString::to_string).collect(),
@@ -2424,6 +2400,99 @@ impl std::fmt::Debug for YellowstoneEntryUpdate {
}
}
/// Server-side Yellowstone keepalive ping update.
#[derive(Clone, Eq, PartialEq)]
pub struct YellowstoneSubscribePingUpdate {
filters: std::vec::Vec<crate::YellowstoneSubscribeFilterName>,
created_at: std::option::Option<crate::YellowstoneUpdateTimestamp>,
}
impl YellowstoneSubscribePingUpdate {
/// Returns echoed matching filter names in server order.
#[must_use]
pub fn filters(&self) -> &[crate::YellowstoneSubscribeFilterName] {
return self.filters.as_slice();
}
/// Returns the optional server creation timestamp.
#[must_use]
pub const fn created_at(&self) -> std::option::Option<crate::YellowstoneUpdateTimestamp> {
return self.created_at;
}
}
impl std::fmt::Debug for YellowstoneSubscribePingUpdate {
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
return formatter
.debug_struct("YellowstoneSubscribePingUpdate")
.field("filter_count", &self.filters.len())
.field("created_at", &self.created_at)
.finish();
}
}
/// Server-side Yellowstone keepalive pong update.
#[derive(Clone, Eq, PartialEq)]
pub struct YellowstoneSubscribePongUpdate {
filters: std::vec::Vec<crate::YellowstoneSubscribeFilterName>,
created_at: std::option::Option<crate::YellowstoneUpdateTimestamp>,
id: i32,
}
impl YellowstoneSubscribePongUpdate {
/// Returns echoed matching filter names in server order.
#[must_use]
pub fn filters(&self) -> &[crate::YellowstoneSubscribeFilterName] {
return self.filters.as_slice();
}
/// Returns the optional server creation timestamp.
#[must_use]
pub const fn created_at(&self) -> std::option::Option<crate::YellowstoneUpdateTimestamp> {
return self.created_at;
}
/// Returns the exact ping identifier echoed by the server.
#[must_use]
pub const fn id(&self) -> i32 {
return self.id;
}
}
impl std::fmt::Debug for YellowstoneSubscribePongUpdate {
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
return formatter
.debug_struct("YellowstoneSubscribePongUpdate")
.field("filter_count", &self.filters.len())
.field("created_at", &self.created_at)
.field("id", &self.id)
.finish();
}
}
/// Any standard Yellowstone update delivered by the bidirectional `Subscribe` stream.
#[derive(Clone, Debug, PartialEq)]
pub enum YellowstoneSubscribeUpdate {
/// Account update.
Account(crate::YellowstoneAccountUpdate),
/// Slot lifecycle update.
Slot(crate::YellowstoneSlotUpdate),
/// Full transaction update.
Transaction(crate::YellowstoneTransactionUpdate),
/// Lightweight transaction-status update.
TransactionStatus(crate::YellowstoneTransactionStatusUpdate),
/// Full block update.
Block(crate::YellowstoneBlockUpdate),
/// Server keepalive ping. KSP replies automatically with a ping request.
Ping(crate::YellowstoneSubscribePingUpdate),
/// Server keepalive pong.
Pong(crate::YellowstoneSubscribePongUpdate),
/// Block-metadata update.
BlockMeta(crate::YellowstoneBlockMetaUpdate),
/// Entry update.
Entry(crate::YellowstoneEntryUpdate),
}
/// Named empty filter activating the standard Yellowstone `blocks_meta` family.
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub struct YellowstoneSubscribeBlocksMetaFilter {
@@ -2437,7 +2506,6 @@ impl YellowstoneSubscribeBlocksMetaFilter {
return Self { _private: () };
}
#[cfg(test)]
fn to_wire(self) -> yellowstone_grpc_proto::geyser::SubscribeRequestFilterBlocksMeta {
return yellowstone_grpc_proto::geyser::SubscribeRequestFilterBlocksMeta::default();
}
@@ -2456,7 +2524,6 @@ impl YellowstoneSubscribeEntryFilter {
return Self { _private: () };
}
#[cfg(test)]
fn to_wire(self) -> yellowstone_grpc_proto::geyser::SubscribeRequestFilterEntry {
return yellowstone_grpc_proto::geyser::SubscribeRequestFilterEntry::default();
}
@@ -2712,7 +2779,6 @@ impl YellowstoneSubscribeRequest {
return std::result::Result::Ok(());
}
#[cfg(test)]
fn to_wire(&self) -> ksp_core_lib::Result<yellowstone_grpc_proto::geyser::SubscribeRequest> {
let validation = self.validate();
if let std::result::Result::Err(error) = validation {
@@ -2770,7 +2836,6 @@ impl YellowstoneSubscribeRequest {
}
}
#[cfg(test)]
fn decode_account_update(wire: yellowstone_grpc_proto::geyser::SubscribeUpdate) -> ksp_core_lib::Result<crate::YellowstoneAccountUpdate> {
let (filters, created_at) = match decode_update_envelope(wire.filters, wire.created_at) {
std::result::Result::Ok(value) => value,
@@ -2790,7 +2855,6 @@ fn decode_account_update(wire: yellowstone_grpc_proto::geyser::SubscribeUpdate)
return std::result::Result::Ok(crate::YellowstoneAccountUpdate { filters, created_at, account, slot: update.slot, is_startup: update.is_startup });
}
#[cfg(test)]
fn decode_slot_update(wire: yellowstone_grpc_proto::geyser::SubscribeUpdate) -> ksp_core_lib::Result<crate::YellowstoneSlotUpdate> {
let (filters, created_at) = match decode_update_envelope(wire.filters, wire.created_at) {
std::result::Result::Ok(value) => value,
@@ -2823,7 +2887,6 @@ fn decode_slot_update(wire: yellowstone_grpc_proto::geyser::SubscribeUpdate) ->
});
}
#[cfg(test)]
fn decode_transaction_update(wire: yellowstone_grpc_proto::geyser::SubscribeUpdate) -> ksp_core_lib::Result<crate::YellowstoneTransactionUpdate> {
let (filters, created_at) = match decode_update_envelope(wire.filters, wire.created_at) {
std::result::Result::Ok(value) => value,
@@ -2843,7 +2906,6 @@ fn decode_transaction_update(wire: yellowstone_grpc_proto::geyser::SubscribeUpda
return std::result::Result::Ok(crate::YellowstoneTransactionUpdate { filters, created_at, transaction, slot: update.slot });
}
#[cfg(test)]
fn decode_transaction_status_update(wire: yellowstone_grpc_proto::geyser::SubscribeUpdate) -> ksp_core_lib::Result<crate::YellowstoneTransactionStatusUpdate> {
let (filters, created_at) = match decode_update_envelope(wire.filters, wire.created_at) {
std::result::Result::Ok(value) => value,
@@ -2875,7 +2937,30 @@ fn decode_transaction_status_update(wire: yellowstone_grpc_proto::geyser::Subscr
});
}
#[cfg(test)]
fn decode_ping_update(wire: yellowstone_grpc_proto::geyser::SubscribeUpdate) -> ksp_core_lib::Result<crate::YellowstoneSubscribePingUpdate> {
let (filters, created_at) = match decode_update_envelope(wire.filters, wire.created_at) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
match wire.update_oneof {
std::option::Option::Some(yellowstone_grpc_proto::geyser::subscribe_update::UpdateOneof::Ping(_)) => {},
_ => return invalid_subscribe_response("ping", "Yellowstone update does not contain a ping payload"),
}
return std::result::Result::Ok(crate::YellowstoneSubscribePingUpdate { filters, created_at });
}
fn decode_pong_update(wire: yellowstone_grpc_proto::geyser::SubscribeUpdate) -> ksp_core_lib::Result<crate::YellowstoneSubscribePongUpdate> {
let (filters, created_at) = match decode_update_envelope(wire.filters, wire.created_at) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let pong = match wire.update_oneof {
std::option::Option::Some(yellowstone_grpc_proto::geyser::subscribe_update::UpdateOneof::Pong(value)) => value,
_ => return invalid_subscribe_response("pong", "Yellowstone update does not contain a pong payload"),
};
return std::result::Result::Ok(crate::YellowstoneSubscribePongUpdate { filters, created_at, id: pong.id });
}
fn decode_block_update(wire: yellowstone_grpc_proto::geyser::SubscribeUpdate) -> ksp_core_lib::Result<crate::YellowstoneBlockUpdate> {
let (filters, created_at) = match decode_update_envelope(wire.filters, wire.created_at) {
std::result::Result::Ok(value) => value,
@@ -2951,7 +3036,6 @@ fn decode_block_update(wire: yellowstone_grpc_proto::geyser::SubscribeUpdate) ->
});
}
#[cfg(test)]
fn decode_block_meta_update(wire: yellowstone_grpc_proto::geyser::SubscribeUpdate) -> ksp_core_lib::Result<crate::YellowstoneBlockMetaUpdate> {
let (filters, created_at) = match decode_update_envelope(wire.filters, wire.created_at) {
std::result::Result::Ok(value) => value,
@@ -2991,7 +3075,6 @@ fn decode_block_meta_update(wire: yellowstone_grpc_proto::geyser::SubscribeUpdat
});
}
#[cfg(test)]
fn decode_entry_update(wire: yellowstone_grpc_proto::geyser::SubscribeUpdate) -> ksp_core_lib::Result<crate::YellowstoneEntryUpdate> {
let (filters, created_at) = match decode_update_envelope(wire.filters, wire.created_at) {
std::result::Result::Ok(value) => value,
@@ -3008,7 +3091,6 @@ fn decode_entry_update(wire: yellowstone_grpc_proto::geyser::SubscribeUpdate) ->
return std::result::Result::Ok(crate::YellowstoneEntryUpdate { filters, created_at, entry });
}
#[cfg(test)]
fn decode_block_rewards(wire: yellowstone_grpc_proto::solana::storage::confirmed_block::Rewards) -> ksp_core_lib::Result<crate::YellowstoneBlockRewards> {
if wire.rewards.len() > MAX_GRPC_BLOCK_VECTOR_COUNT {
return invalid_subscribe_response("block.rewards", "Yellowstone block reward count exceeds the KSP bound");
@@ -3024,7 +3106,6 @@ fn decode_block_rewards(wire: yellowstone_grpc_proto::solana::storage::confirmed
return std::result::Result::Ok(crate::YellowstoneBlockRewards { rewards, num_partitions: wire.num_partitions.map(|value| return value.num_partitions) });
}
#[cfg(test)]
fn decode_entry_info(wire: yellowstone_grpc_proto::geyser::SubscribeUpdateEntry) -> ksp_core_lib::Result<crate::YellowstoneEntryInfo> {
let hash = match decode_entry_hash(wire.hash) {
std::result::Result::Ok(value) => value,
@@ -3040,7 +3121,6 @@ fn decode_entry_info(wire: yellowstone_grpc_proto::geyser::SubscribeUpdateEntry)
});
}
#[cfg(test)]
fn decode_entry_hash(bytes: std::vec::Vec<u8>) -> ksp_core_lib::Result<crate::YellowstoneHashBytes> {
let bytes: [u8; YELLOWSTONE_HASH_LENGTH_BYTES] = match bytes.try_into() {
std::result::Result::Ok(value) => value,
@@ -3049,7 +3129,6 @@ fn decode_entry_hash(bytes: std::vec::Vec<u8>) -> ksp_core_lib::Result<crate::Ye
return std::result::Result::Ok(crate::YellowstoneHashBytes { bytes });
}
#[cfg(test)]
fn decode_blockhash_text(field: &'static str, value: std::string::String) -> ksp_core_lib::Result<std::string::String> {
if value.is_empty()
|| value.len() > MAX_GRPC_BLOCKHASH_TEXT_LENGTH_BYTES
@@ -3061,7 +3140,6 @@ fn decode_blockhash_text(field: &'static str, value: std::string::String) -> ksp
return std::result::Result::Ok(value);
}
#[cfg(test)]
fn decode_transaction_info(wire: yellowstone_grpc_proto::geyser::SubscribeUpdateTransactionInfo) -> ksp_core_lib::Result<crate::YellowstoneTransactionInfo> {
let signature = match decode_transaction_signature("transaction.signature", wire.signature) {
std::result::Result::Ok(value) => value,
@@ -3084,7 +3162,6 @@ fn decode_transaction_info(wire: yellowstone_grpc_proto::geyser::SubscribeUpdate
return std::result::Result::Ok(crate::YellowstoneTransactionInfo { signature, is_vote: wire.is_vote, transaction, meta, index: wire.index });
}
#[cfg(test)]
fn decode_stored_transaction(
wire: yellowstone_grpc_proto::solana::storage::confirmed_block::Transaction,
) -> ksp_core_lib::Result<crate::YellowstoneStoredTransaction> {
@@ -3109,7 +3186,6 @@ fn decode_stored_transaction(
return std::result::Result::Ok(crate::YellowstoneStoredTransaction { signatures, message });
}
#[cfg(test)]
fn decode_transaction_message(
wire: yellowstone_grpc_proto::solana::storage::confirmed_block::Message,
) -> ksp_core_lib::Result<crate::YellowstoneTransactionMessage> {
@@ -3174,7 +3250,6 @@ fn decode_transaction_message(
});
}
#[cfg(test)]
fn decode_compiled_instruction(
wire: yellowstone_grpc_proto::solana::storage::confirmed_block::CompiledInstruction,
) -> ksp_core_lib::Result<crate::YellowstoneCompiledInstruction> {
@@ -3188,7 +3263,6 @@ fn decode_compiled_instruction(
});
}
#[cfg(test)]
fn decode_message_address_table_lookup(
wire: yellowstone_grpc_proto::solana::storage::confirmed_block::MessageAddressTableLookup,
) -> ksp_core_lib::Result<crate::YellowstoneMessageAddressTableLookup> {
@@ -3206,7 +3280,6 @@ fn decode_message_address_table_lookup(
});
}
#[cfg(test)]
fn decode_transaction_status_meta(
wire: yellowstone_grpc_proto::solana::storage::confirmed_block::TransactionStatusMeta,
) -> ksp_core_lib::Result<crate::YellowstoneTransactionStatusMeta> {
@@ -3310,7 +3383,6 @@ fn decode_transaction_status_meta(
});
}
#[cfg(test)]
fn decode_inner_instructions(
wire: yellowstone_grpc_proto::solana::storage::confirmed_block::InnerInstructions,
) -> ksp_core_lib::Result<crate::YellowstoneInnerInstructions> {
@@ -3332,7 +3404,6 @@ fn decode_inner_instructions(
return std::result::Result::Ok(crate::YellowstoneInnerInstructions { index: wire.index, instructions });
}
#[cfg(test)]
fn decode_token_balance(wire: yellowstone_grpc_proto::solana::storage::confirmed_block::TokenBalance) -> ksp_core_lib::Result<crate::YellowstoneTokenBalance> {
if wire.mint.len() > MAX_GRPC_TRANSACTION_TEXT_LENGTH_BYTES
|| wire.owner.len() > MAX_GRPC_TRANSACTION_TEXT_LENGTH_BYTES
@@ -3363,7 +3434,6 @@ fn decode_token_balance(wire: yellowstone_grpc_proto::solana::storage::confirmed
});
}
#[cfg(test)]
fn decode_return_data(wire: yellowstone_grpc_proto::solana::storage::confirmed_block::ReturnData) -> ksp_core_lib::Result<crate::YellowstoneReturnData> {
if wire.data.len() > MAX_GRPC_TRANSACTION_RETURN_DATA_BYTES {
return invalid_subscribe_response("transaction.meta.return_data", "Yellowstone transaction return data exceeds the KSP bound");
@@ -3375,7 +3445,6 @@ fn decode_return_data(wire: yellowstone_grpc_proto::solana::storage::confirmed_b
return std::result::Result::Ok(crate::YellowstoneReturnData { program_id, data: wire.data });
}
#[cfg(test)]
fn decode_reward(wire: yellowstone_grpc_proto::solana::storage::confirmed_block::Reward) -> ksp_core_lib::Result<crate::YellowstoneReward> {
if wire.pubkey.len() > MAX_GRPC_TRANSACTION_TEXT_LENGTH_BYTES
|| wire.commission.len() > MAX_GRPC_TRANSACTION_TEXT_LENGTH_BYTES
@@ -3410,7 +3479,6 @@ fn decode_reward(wire: yellowstone_grpc_proto::solana::storage::confirmed_block:
});
}
#[cfg(test)]
fn decode_transaction_error(
field: &'static str,
wire: yellowstone_grpc_proto::solana::storage::confirmed_block::TransactionError,
@@ -3421,7 +3489,6 @@ fn decode_transaction_error(
return std::result::Result::Ok(crate::YellowstoneTransactionError { bytes: wire.err });
}
#[cfg(test)]
fn decode_transaction_signature(field: &'static str, bytes: std::vec::Vec<u8>) -> ksp_core_lib::Result<crate::YellowstoneTransactionSignature> {
let bytes: [u8; YELLOWSTONE_TRANSACTION_SIGNATURE_WIRE_LENGTH_BYTES] = match bytes.try_into() {
std::result::Result::Ok(value) => value,
@@ -3430,7 +3497,6 @@ fn decode_transaction_signature(field: &'static str, bytes: std::vec::Vec<u8>) -
return std::result::Result::Ok(crate::YellowstoneTransactionSignature::new(bytes));
}
#[cfg(test)]
fn decode_hash_bytes(field: &'static str, bytes: std::vec::Vec<u8>) -> ksp_core_lib::Result<crate::YellowstoneHashBytes> {
let bytes: [u8; YELLOWSTONE_HASH_LENGTH_BYTES] = match bytes.try_into() {
std::result::Result::Ok(value) => value,
@@ -3439,7 +3505,6 @@ fn decode_hash_bytes(field: &'static str, bytes: std::vec::Vec<u8>) -> ksp_core_
return std::result::Result::Ok(crate::YellowstoneHashBytes { bytes });
}
#[cfg(test)]
fn decode_update_envelope(
filters: std::vec::Vec<std::string::String>,
created_at: std::option::Option<yellowstone_grpc_proto::prost_types::Timestamp>,
@@ -3471,7 +3536,6 @@ fn decode_update_envelope(
return std::result::Result::Ok((decoded_filters, decoded_created_at));
}
#[cfg(test)]
fn decode_account_info(wire: yellowstone_grpc_proto::geyser::SubscribeUpdateAccountInfo) -> ksp_core_lib::Result<crate::YellowstoneAccountInfo> {
if wire.data.len() > MAX_GRPC_SUBSCRIBE_ACCOUNT_DATA_LENGTH_BYTES {
return invalid_subscribe_response("account.data", "Yellowstone account data exceeds the KSP bound");
@@ -3508,7 +3572,6 @@ fn decode_account_info(wire: yellowstone_grpc_proto::geyser::SubscribeUpdateAcco
});
}
#[cfg(test)]
fn decode_pubkey_bytes(field: &'static str, bytes: std::vec::Vec<u8>) -> ksp_core_lib::Result<ksp_core_lib::Pubkey> {
let array: [u8; 32] = match bytes.try_into() {
std::result::Result::Ok(value) => value,
@@ -3588,16 +3651,53 @@ fn validate_memcmp_text(value: &str) -> ksp_core_lib::Result<()> {
return std::result::Result::Ok(());
}
/// Converts one validated KSP subscribe request to the internal Yellowstone protobuf wire.
pub(crate) fn yellowstone_subscribe_request_to_wire(
request: &crate::YellowstoneSubscribeRequest,
) -> ksp_core_lib::Result<yellowstone_grpc_proto::geyser::SubscribeRequest> {
return request.to_wire();
}
/// Decodes one internal Yellowstone protobuf update into the complete KSP-owned update enum.
pub(crate) fn yellowstone_subscribe_update_from_wire(
wire: yellowstone_grpc_proto::geyser::SubscribeUpdate,
) -> ksp_core_lib::Result<crate::YellowstoneSubscribeUpdate> {
let kind = match wire.update_oneof.as_ref() {
std::option::Option::Some(yellowstone_grpc_proto::geyser::subscribe_update::UpdateOneof::Account(_)) => 1_u8,
std::option::Option::Some(yellowstone_grpc_proto::geyser::subscribe_update::UpdateOneof::Slot(_)) => 2_u8,
std::option::Option::Some(yellowstone_grpc_proto::geyser::subscribe_update::UpdateOneof::Transaction(_)) => 3_u8,
std::option::Option::Some(yellowstone_grpc_proto::geyser::subscribe_update::UpdateOneof::TransactionStatus(_)) => 4_u8,
std::option::Option::Some(yellowstone_grpc_proto::geyser::subscribe_update::UpdateOneof::Block(_)) => 5_u8,
std::option::Option::Some(yellowstone_grpc_proto::geyser::subscribe_update::UpdateOneof::Ping(_)) => 6_u8,
std::option::Option::Some(yellowstone_grpc_proto::geyser::subscribe_update::UpdateOneof::Pong(_)) => 7_u8,
std::option::Option::Some(yellowstone_grpc_proto::geyser::subscribe_update::UpdateOneof::BlockMeta(_)) => 8_u8,
std::option::Option::Some(yellowstone_grpc_proto::geyser::subscribe_update::UpdateOneof::Entry(_)) => 9_u8,
std::option::Option::None => {
return invalid_subscribe_response("update.oneof", "Yellowstone subscribe update is missing its oneof payload");
},
};
return match kind {
1 => decode_account_update(wire).map(crate::YellowstoneSubscribeUpdate::Account),
2 => decode_slot_update(wire).map(crate::YellowstoneSubscribeUpdate::Slot),
3 => decode_transaction_update(wire).map(crate::YellowstoneSubscribeUpdate::Transaction),
4 => decode_transaction_status_update(wire).map(crate::YellowstoneSubscribeUpdate::TransactionStatus),
5 => decode_block_update(wire).map(crate::YellowstoneSubscribeUpdate::Block),
6 => decode_ping_update(wire).map(crate::YellowstoneSubscribeUpdate::Ping),
7 => decode_pong_update(wire).map(crate::YellowstoneSubscribeUpdate::Pong),
8 => decode_block_meta_update(wire).map(crate::YellowstoneSubscribeUpdate::BlockMeta),
9 => decode_entry_update(wire).map(crate::YellowstoneSubscribeUpdate::Entry),
_ => invalid_subscribe_response("update.oneof", "Yellowstone subscribe update kind is unsupported"),
};
}
fn invalid_subscribe_parameter<T>(field: &'static str, message: &'static str) -> ksp_core_lib::Result<T> {
return std::result::Result::Err(ksp_core_lib::Error::new(crate::ERROR_CODE_INVALID_RPC_PARAMETERS, message).with_context("field", field));
}
#[cfg(test)]
fn invalid_subscribe_response<T>(field: &'static str, message: &'static str) -> ksp_core_lib::Result<T> {
return std::result::Result::Err(ksp_core_lib::Error::new(crate::ERROR_CODE_INVALID_RESPONSE, message).with_context("grpc_update", field));
}
#[cfg(test)]
fn commitment_to_wire(commitment: std::option::Option<crate::SolanaCommitment>) -> std::option::Option<i32> {
return commitment.map(|value| {
return match value {