All 19 published crates are on crates.io at version 0.9.0:
shipstern, shipstern-core, shipstern-proto, shipstern-proc-macro, shipstern-parser, shipstern-mock, shipstern-stream, shipstern-bpf-loader-parser, shipstern-spl-token-parser, shipstern-spl-token-extensions-parser, shipstern-block-meta-parser, shipstern-slot-parser, shipstern-stake-pool-parser, shipstern-solana-rpc-source, shipstern-yellowstone-grpc-source, shipstern-yellowstone-fumarole-source, shipstern-solana-snapshot-source, shipstern-jetstream-source, shipstern-block-coordinator.
See CHANGELOG.md for the full history.
Changed
- Breaking for code that matches on
PrefilterErroror builds a prefilter with a struct literal.PrefilterErrorgained variants for the account-filter and data-slice checks, andAccountPrefilter,TransactionPrefilterandSlotPrefiltereach gained fields. Neither type is#[non_exhaustive], so an exhaustivematchon the error and anyAccountPrefilter { accounts, owners }literal stop compiling; add a wildcard arm and..Default::default()respectively. Builder users are unaffected (#303). - Bumped
yellowstone-grpc-protofrom12.4to12.6, picking up the Transaction V1 (SIMD-0385)Message.configfield and thecuckoo_account_includetransaction filter. The new filter is not exposed throughTransactionFilterand is always sent asNone(#304 by @ultrasilicon). shipstern-jetstream-source: a parser registered on theblockpipeline whose prefilter setsblock_metaorslotbut none ofinclude_transactions/include_accounts/include_entriesno longer receives aBlockupdate. Previously anyblock_meta/slotprefilter forced its filter ID into the block match list, so such a parser received a header-onlyBlock:transactionsandaccountswere always empty. Use ablock_metapipeline instead.
Deprecated
shipstern-proc-macro: thecpi_event_discriminatorandcpi_event_payload_offsetmacro arguments are ignored, with a deprecation warning at the call site, when the IDL declares a CPI event envelope. They still apply to IDLs that declare none. Both arguments are removed in 0.10 (#299 by @senzenn).
Added
- The Yellowstone gRPC source replaces the live subscription mid-stream, so a changing filter set no longer costs a reconnect.
Runtime::handlehands out a cheapCloneRuntimeHandlebeforerunconsumes the runtime;filtersreports the last set handed to the source,update_filterspatches it under a lock,send_filter_updatereplaces it wholesale, andreset_filtersrestores the registered set. The handle exists only for sources implementingFilterUpdateSource, which today is gRPC alone, so taking one from any other source is a compile error rather than a runtime one. Keys are parser IDs, except for instruction parsers, which the runtime bundles behind a singleInstructionPipeline::IDentry. A set naming a parser with no registered pipeline is refused withFilterUpdateError::UnknownParserbefore anything is sent, andOk(())means the set reached the source rather than that the server applied it (#302 by @senzenn, #305 and #307 by @kespinola). Filtersgainedget,parser_ids,insert,merge, andremove, keyed by parser ID, so the next subscription can be built without reaching into the map by hand (#305 by @kespinola).Prefiltercan express the rest of Yellowstone's subscription surface, whichimpl From<Filters> for SubscribeRequestpreviously hardcoded to empty.AccountPrefiltergainedfilters(memcmp, data size, token-account state, and lamport comparisons, via the newAccountFilter,MemcmpDataandLamportsCmptypes) andnonempty_txn_signature;TransactionPrefiltergainedaccounts_exclude,voteandsignature;SlotPrefiltergainedinterslot_updates; and the Yellowstone gRPC source config gainedaccounts-data-slice, which is request-level rather than per-parser. Builder setters check account filters against the rules the server enforces when it builds its own filter (memcmp encoding and size, filter count, at most one data size, notoken-account-state = false), so a bad config fails at build time instead of taking the subscription down when it is opened;YellowstoneGrpcConfig::validatechecks the data-slice windows for order and overlap, and the source calls it before it dials. Every field defaults to the previous behaviour.transactions_statusandentrystay unsupported: they are separate subscription kinds with no pipeline behind them, so nothing could consume what they delivered (#303).shipstern-core:InstructionSharedgainedtransaction_config: Option<TransactionConfig>, the inline compute budget that Transaction V1 (SIMD-0385) carries on the message instead of in top-levelComputeBudgetinstructions. It exposes the priority fee, compute-unit limit, loaded-accounts data-size limit, and heap size. It isNonefor Legacy and V0 transactions and for jetstream-source transactions, which are decoded from an SDK without a V1 message variant (#304 by @ultrasilicon).shipstern-proc-macro: generated account types and theInstructionswrapper now exposeDISCRIMINATORandDISCRIMINATOR_OFFSETconstants, so consumers can buildmemcmpfilters and route on discriminators without re-deriving the bytes from the IDL. The pair is a memcmp predicate: the bytes the parser compares at that offset. It is not a payload boundary, because numeric discriminators (for example SPL Governance) are re-read as the first field of the account body, so decoding still goes throughtry_unpack. No constant is emitted where the parser could not honor it: size-only discriminators, zero-length discriminators, fixed-size fields whose declared width disagrees with the decoded default bytes, and instruction names that collide after case folding (#294).shipstern-proc-macro: the CPI event envelope is read from the IDL. An IDL that declares the self-CPI envelope oneventNode.discriminators, the form Carbon and@codama/renderers-vixen-parseremit, previously failed to build with an event discriminator collision, because every event was keyed on the first discriminator in its chain, which for an enveloped IDL is the shared envelope tag.EVENT_PAYLOAD_OFFSEThad the mirror problem: it came from the macro arguments and defaulted to 8, so the CPI path always stripped a fixed byte count and only happened to be right for a standard Anchor tag. The macro now infers the envelope from the chain (a constant at offset 0 is the tag, the next discriminator's declared offset is the payload offset), checks that every declaring event agrees on both, rebases the remaining discriminators so the CPI and log paths share one layout, and ANDs a chain of two or more. Padded layouts round-trip because the payload offset is the declared offset rather than the tag length. Chains that cannot be honored fail the build instead of parsing arbitrarily: two constants at offset 0, overlapping ranges, a mix of constant and non-constant nodes behind a tag, an event whose only discriminator is the tag, or discriminator bytes that do not decode, which previously panicked the macro. A build-time guard also rejects an envelope tag that prefixes an instruction discriminator at offset 0 in either direction, because the parser filters any instruction whose data starts with the tag before dispatch; it checks the tag actually in use, whether from the IDL, the macro arguments, or the Anchor default. Instruction parsing is untouched (#299 by @senzenn).
Fixed
shipstern-jetstream-source: emitSubscribeUpdateBlockMetaandSubscribeUpdateSlotfor filters that request them.block_metaandslotprefilters were previously bucketed into the block match list, so their filter IDs rode onUpdateOneof::Block. The runtime dispatches by variant, so those IDs matched no pipeline and were dropped with only atrace!line: block-meta and slot parsers ran to completion having handled zero updates, andshipstern-block-coordinator, which keys onBlockMeta, received none of it on the historical-replay path (delivering it is a prerequisite for driving that crate from replay, not on its own sufficient). Both messages are built from fields already carried onBlockData::Block. Replayed slots reportSLOT_FINALIZED, since Old Faithful archives hold only finalized history and cannot reproduce the processed/confirmed transitions thatSlotPrefilter::filter_by_commitment = falseasks for.
What's Changed
- ci: bust cargo cache keys after the org transfer by @senzenn in #298
- feat(proc-macro): expose discriminator constants on generated types by @senzenn in #295
- feat(proc-macro): read the CPI event envelope from the IDL by @senzenn in #299
- feat(core): expose Transaction V1 inline budget (SIMD-0385) by @ultrasilicon in #304
- docs(changelog): release notes for Transaction V1 inline budget (#304) by @kespinola in #306
- chore(deps): bump tar from 0.4.45 to 0.4.46 by @dependabot[bot] in #290
- chore(deps): bump serde_with from 3.16.1 to 3.22.0 by @dependabot[bot] in #291
- chore(deps): bump rpassword from 7.4.0 to 7.5.4 by @dependabot[bot] in #292
- feat(runtime): update gRPC filters on a live subscription by @senzenn in #302
- fix(jetstreamer-source): deliver block meta and slot updates to their pipelines by @senzenn in #287
- feat(core): implement the remaining SubscribeRequest filters by @senzenn in #309
- chore(release): 0.9.0 by @kespinola in #312
New Contributors
- @ultrasilicon made their first contribution in #304
- @dependabot[bot] made their first contribution in #290
Full Changelog: v0.8.0...v0.9.0