v0.3.13-pre.002

This commit is contained in:
2026-09-10 09:50:42 +02:00
parent ee0359efd5
commit 793178b345
15 changed files with 976 additions and 41 deletions

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-onchain-transport-lib/src/grpc_subscribe.rs
// version: 8
// version: 9
const MAX_GRPC_BLOCKHASH_TEXT_LENGTH_BYTES: usize = 128;
const MAX_GRPC_BLOCK_VECTOR_COUNT: usize = 65_536;
@@ -2529,13 +2529,34 @@ impl YellowstoneSubscribeEntryFilter {
}
}
/// Opaque deterministic identity material for one complete Yellowstone Subscribe request.
///
/// The encoded bytes remain private. `Hash` feeds those canonical bytes to a caller-provided hasher while `Debug` exposes only their length.
#[derive(Clone, Eq, PartialEq)]
pub struct YellowstoneSubscribeRequestIdentity {
bytes: std::vec::Vec<u8>,
}
impl std::hash::Hash for crate::YellowstoneSubscribeRequestIdentity {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
state.write(&(self.bytes.len() as u64).to_be_bytes());
state.write(self.bytes.as_slice());
return;
}
}
impl std::fmt::Debug for crate::YellowstoneSubscribeRequestIdentity {
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
return formatter.debug_struct("YellowstoneSubscribeRequestIdentity").field("byte_len", &self.bytes.len()).finish();
}
}
/// Provider-neutral standard Yellowstone subscribe request owned by KSP.
///
/// The seven upstream maps are represented independently and retain named empty entries. An entirely empty map is the logical KSP representation of no active
/// filter in that family; protobuf map encoding does not distinguish an omitted map from an empty map. Filter-group names are globally unique across all seven
/// maps so the names echoed by `SubscribeUpdate.filters` remain unambiguous. `Debug` exposes only counts and common scalar options, never filter names or
/// future
/// filter payloads.
/// future filter payloads.
#[derive(Clone, Eq, PartialEq)]
pub struct YellowstoneSubscribeRequest {
accounts: std::collections::BTreeMap<crate::YellowstoneSubscribeFilterName, crate::YellowstoneSubscribeAccountFilter>,
@@ -2551,7 +2572,7 @@ pub struct YellowstoneSubscribeRequest {
from_slot: std::option::Option<u64>,
}
impl YellowstoneSubscribeRequest {
impl crate::YellowstoneSubscribeRequest {
/// Creates an empty subscribe request. Empty requests are valid because later bidi lifecycle code uses request mutations to clear filters or carry ping
/// state.
#[must_use]
@@ -2762,6 +2783,40 @@ impl YellowstoneSubscribeRequest {
return self.from_slot;
}
/// Builds one opaque deterministic identity for the complete logical Subscribe request.
///
/// The identity preserves filter-family separation, globally sorted filter names, exact filter wire payloads and common request options. Its Debug surface
/// exposes only the encoded byte length. Callers may hash the opaque value but cannot recover the underlying identity bytes through this API.
pub fn identity(&self) -> ksp_core_lib::Result<crate::YellowstoneSubscribeRequestIdentity> {
let validation = self.validate();
if let std::result::Result::Err(error) = validation {
return std::result::Result::Err(error);
}
let mut bytes = std::vec::Vec::new();
append_subscribe_identity_map(&mut bytes, b"accounts", &self.accounts, |filter| return filter.to_wire());
append_subscribe_identity_map(&mut bytes, b"blocks", &self.blocks, |filter| return filter.to_wire());
append_subscribe_identity_map(&mut bytes, b"blocks_meta", &self.blocks_meta, |filter| return filter.to_wire());
append_subscribe_identity_map(&mut bytes, b"entry", &self.entry, |filter| return filter.to_wire());
append_subscribe_identity_map(&mut bytes, b"slots", &self.slots, |filter| return filter.to_wire());
append_subscribe_identity_map(&mut bytes, b"transactions", &self.transactions, |filter| return filter.to_wire());
append_subscribe_identity_map(&mut bytes, b"transactions_status", &self.transactions_status, |filter| return filter.to_wire());
let mut common = match self.to_wire() {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
common.accounts.clear();
common.blocks.clear();
common.blocks_meta.clear();
common.entry.clear();
common.slots.clear();
common.transactions.clear();
common.transactions_status.clear();
let common = yellowstone_grpc_proto::prost::Message::encode_to_vec(&common);
append_subscribe_identity_component(&mut bytes, b"common");
append_subscribe_identity_component(&mut bytes, common.as_slice());
return std::result::Result::Ok(crate::YellowstoneSubscribeRequestIdentity { bytes });
}
/// Validates all deterministic common subscribe-request bounds before any network I/O.
pub fn validate(&self) -> ksp_core_lib::Result<()> {
if self.total_filter_count() > MAX_GRPC_SUBSCRIBE_FILTER_GROUP_COUNT {
@@ -3710,13 +3765,38 @@ fn commitment_to_wire(commitment: std::option::Option<crate::SolanaCommitment>)
});
}
impl std::default::Default for YellowstoneSubscribeRequest {
fn append_subscribe_identity_component(output: &mut std::vec::Vec<u8>, value: &[u8]) {
output.extend_from_slice(&(value.len() as u64).to_be_bytes());
output.extend_from_slice(value);
return;
}
fn append_subscribe_identity_map<V, W, F>(
output: &mut std::vec::Vec<u8>,
family: &[u8],
values: &std::collections::BTreeMap<crate::YellowstoneSubscribeFilterName, V>,
mut to_wire: F,
) where
W: yellowstone_grpc_proto::prost::Message,
F: FnMut(&V) -> W,
{
append_subscribe_identity_component(output, family);
output.extend_from_slice(&(values.len() as u64).to_be_bytes());
for (name, filter) in values {
append_subscribe_identity_component(output, name.as_str().as_bytes());
let wire = yellowstone_grpc_proto::prost::Message::encode_to_vec(&to_wire(filter));
append_subscribe_identity_component(output, wire.as_slice());
}
return;
}
impl std::default::Default for crate::YellowstoneSubscribeRequest {
fn default() -> Self {
return Self::new();
}
}
impl std::fmt::Debug for YellowstoneSubscribeRequest {
impl std::fmt::Debug for crate::YellowstoneSubscribeRequest {
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
return formatter
.debug_struct("YellowstoneSubscribeRequest")

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-onchain-transport-lib/src/lib.rs
// version: 46
// version: 47
#![warn(missing_docs)]
#![deny(unreachable_pub)]
@@ -215,6 +215,8 @@ pub use self::grpc_subscribe::YellowstoneSubscribePingUpdate;
pub use self::grpc_subscribe::YellowstoneSubscribePongUpdate;
/// Provider-neutral standard Yellowstone Subscribe request.
pub use self::grpc_subscribe::YellowstoneSubscribeRequest;
/// Opaque deterministic identity for one complete Yellowstone Subscribe request.
pub use self::grpc_subscribe::YellowstoneSubscribeRequestIdentity;
/// Complete slot-family filter group for standard Yellowstone Subscribe.
pub use self::grpc_subscribe::YellowstoneSubscribeSlotFilter;
/// Complete transaction-family filter shared by transactions and transaction-status maps.