Subscription registry and event fan-out, shared by every provider.
This is the part of a streaming implementation that is the same whatever the chain data comes from: keeping track of who is subscribed to what, deciding which events reach whom, gating on confirmation depth, and turning a block into per-subscription deltas. What differs per backend — polling REST, following a gRPC stream, driving an emulator, replaying a chain store — sits above this, and hands it AppliedBlocks.
State is guarded by this and every operation runs on the caller's thread. That is not a simplification of the threaded design, it is a different trade: registration and fan-out are ordered by the caller's own program order, which makes subscribe(q); submit(tx) race-free without any happens-before argument about a queue. It also compiles to Scala.js, where there is no thread to hand work to.
Events are handed to mailboxes outside the monitor. A consumer's continuation can run inline on offer, and that continuation is allowed to cancel its subscription, which re-enters this hub — holding the lock across offer would deadlock on exactly that path.
Events are buffered into mailboxes under the lock and delivered after releasing it. Both halves matter. Buffering under the lock is what makes a registration plus its seed one indivisible step, so a subscriber can never see a live Spent before the Created it belongs after. Delivering outside it is what keeps a consumer's continuation — which may cancel, and so re-enter this hub — from running while the monitor is held.
Fail every subscription with cause, and stop accepting new ones.
Fail every subscription with cause, and stop accepting new ones.
Distinct from closeAll, and the distinction is the subscriber's whole world: a closed stream ended, so whatever it delivered was the truth; a failed stream means the view is untrustworthy and must be rebuilt. A follower that loses track of the chain owes subscribers the second, never the first.
Register a tip subscription and immediately deliver the current tip — a latest-value stream that made you wait for the next change before telling you anything would be useless as the one-shot's dual.
Register a tip subscription and immediately deliver the current tip — a latest-value stream that made you wait for the next change before telling you anything would be useless as the one-shot's dual.
Register a UTxO subscription, optionally seeding it from a snapshot.
Register a UTxO subscription, optionally seeding it from a snapshot.
The seed is buffered under the same lock live events take, so a subscriber cannot observe a live event before the seed it belongs after; it is delivered once the lock is released.
Seeded events carry ChainPoint.origin rather than the current tip. They describe UTxOs produced in blocks the subscription never saw, so stamping them with the tip would make a later rollback past that tip instruct the subscriber to discard state that is still on chain. origin says what is true: this came from a snapshot, not from a block you observed.
Roll back to target, which must still be within securityParam of the tip.
Roll back to target, which must still be within securityParam of the tip.
Only subscriptions that actually emitted something past target see a RolledBack — a subscription gated on confirmations may never have been told about the orphaned blocks at all, and telling it to undo events it never received would be worse than silence.
The status this hub is currently reporting for a transaction, if it is tracking one.
The status this hub is currently reporting for a transaction, if it is tracking one.
None means the hub has no opinion — the transaction was never submitted through this provider and never appeared in a block it applied — and the caller should fall back to whatever it considers authoritative.
Report a protocol-parameter change to subscribers.
Report a protocol-parameter change to subscribers.
The provider's job, not the hub's: only the provider knows what a parameter change looks like on its own source — an epoch boundary observed over chain-sync, a fresh /epochs/latest/parameters, a re-read of local state. The hub cannot detect one, so a provider that never calls this has a subscribeProtocolParams stream that emits the value it was constructed with and nothing further. For an emulator that is exactly right: its parameters are fixed at construction and only its slot advances.
Depth at which a block counts as settled. Taken from the provider's own declaration rather than a separate constructor parameter, so the classifier deciding whether a subscription is serviceable and the hub deciding when to release it cannot disagree.
Depth at which a block counts as settled. Taken from the provider's own declaration rather than a separate constructor parameter, so the classifier deciding whether a subscription is serviceable and the hub deciding when to release it cannot disagree.