Skip to main content

HoprTicketManager

Struct HoprTicketManager 

Source
pub struct HoprTicketManager<S, Q> {
    channel_tickets: Arc<CachedQueueMap<Q>>,
    store: Arc<RwLock<S>>,
}
Expand description

Keeps track of incoming redeemable tickets and provides ticket redemption and neglection operations.

To synchronize the on-chain state with the store, it is advised to call sync_incoming_channels early after the construction of the manager, to make sure outdated data is discarded early. This is typically done only once after construction and not needed to be done during the life-time of the manager.

The manager is safe to be shared via an Arc.

This usage is for Relay nodes only because other types of nodes do not need to keep track of incoming redeemable tickets.

§Usage in incoming packet pipeline

The incoming packet pipeline usually just calls the insert_incoming_ticket whenever a new winning, redeemable ticket is received on an incoming channel.

§Redeemable ticket extraction

On Relay nodes, the manager maintains FIFO queues of redeemable tickets per incoming channel. There are two ways to extract tickets from the queue on a Relay:

  1. redeeming them via redeem_stream
  2. neglecting them via neglect_tickets

Both of these operations extract the tickets in the FIFO order from the queue, making sure that they are always processed in their natural order (by epoch and index).

Both ticket extraction operations are mutually exclusive and cannot be performed simultaneously.

§Locking and lock-contention

There are several methods in the HoprTicketManager object that are expected to be called in the highly performance-sensitive code, on a per-packet basis.

§Incoming winning ticket retrieval

The insert_incoming_ticket method is designed to be high-performance and to be called per each incoming packet after it has been forwarded to a next hop.

This operation acquires the write-part of an RW lock (per incoming channel). This may block the hot-path only if one of the following (also write) operations is performed: 1. Ticket redemption has just finished in that particular channel, and the redeemed ticket is dropped from the same incoming channel queue. 2. Ticket neglection has just finished in that particular channel, and the neglected ticket is dropped from the same incoming channel queue.

Both of these operations happen rarely, and the write lock is usually held only for a short time. In addition, incoming winning tickets are not supposed to usually happen very often. Therefore, high contention on the write lock is not expected.

§Incoming unacknowledged ticket verification

The unrealized_value method is designed to be high-performance and to be called per each incoming packet before it is forwarded to a next hop.

This operation acquires the read-part of an RW lock (per incoming channel). This may block the hot-path only if one of the following (write) operations is performed at the same moment: 1. A new incoming winning ticket is inserted into the same incoming channel queue. 2. Ticket redemption has just finished in that particular channel, and the redeemed ticket is dropped from the same incoming channel queue. 3. Ticket neglection has just finished in that particular channel, and the neglected ticket is dropped from the same incoming channel queue.

All 3 of these operations are not expected to happen very often on a single channel; therefore, high contention on the RW lock is not expected.

Fields§

§channel_tickets: Arc<CachedQueueMap<Q>>§store: Arc<RwLock<S>>

Implementations§

Source§

impl<S> HoprTicketManager<S, S::Queue>
where S: OutgoingIndexStore + TicketQueueStore + 'static, S::Queue: Send + Sync + 'static,

Source

pub fn new_with_factory(store: S) -> (Self, HoprTicketFactory<S>)

Creates the ticket manager in a pair with HoprTicketFactory, both backed by the given store.

The store must be OutgoingIndexStore and TicketQueueStore.

Source§

impl<S> HoprTicketManager<S, S::Queue>
where S: TicketQueueStore + Send + Sync + 'static, S::Queue: Send + Sync + 'static,

Source

pub fn sync_from_incoming_channels( &self, incoming_channels: &[ChannelEntry], ) -> Result<Vec<VerifiedTicket>, TicketManagerError>

Synchronizes the existing incoming redeemable ticket queues with the state of the current incoming_channels.

Any incoming ticket queues that correspond to a channel that is no longer open or effectively open (in incoming_channels) will be dropped and the tickets neglected.

For all opened or effectively opened incoming channels inside incoming_channels, either an existing ticket queue is opened or a new one is created (without any tickets in it).

If there are any unredeemable tickets in the existing queues (with an older epoch or lower index than the current index), they are neglected as well.

All the neglected tickets are returned from the function to make further accounting possible, but they are no longer redeemable.

It is advised to call this function early after the construction of the HoprTicketManager to ensure pruning of dangling or out-of-date values.

Source

pub fn unrealized_value( &self, channel_id: &ChannelId, min_index: Option<u64>, ) -> Result<Option<HoprBalance>, TicketManagerError>

Inserts a new incoming winning redeemable ticket into the ticket manager.

On success, the method returns all tickets that have been neglected in the ticket queue of this channel, in case the inserted ticket has a greater channel epoch than the next extractable ticket in the queue. This situation can happen when unredeemed tickets are left in the queue, while the corresponding channel restarts its lifecycle and a new winning ticket is received. Otherwise, the returned vector is empty. Returns the total value of unredeemed tickets in the given channel and its latest epoch.

NOTE: The function is less efficient when the min_index is specified, as a full scan of the queue is required to calculate the unrealized value.

Trait Implementations§

Source§

impl<S: Debug, Q: Debug> Debug for HoprTicketManager<S, Q>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<S> TicketManagement for HoprTicketManager<S, S::Queue>
where S: TicketQueueStore + Send + Sync + 'static, S::Queue: Send + Sync + 'static,

Source§

fn redeem_stream<C: ChainWriteTicketOperations + Send + Sync + 'static>( &self, chain: C, channel_id: ChannelId, min_amount: Option<HoprBalance>, ) -> Result<impl Stream<Item = Result<RedemptionResult, Self::Error>> + Send, Self::Error>

Creates a stream that redeems tickets in-order one by one in the given channel, using the given [ChainWriteTicketOperations] on-chain client implementation.

If min_redeem_value is given, all the tickets that are lower than the given value are neglected in the process.

If there’s already an existing redeem stream for the channel, an error is returned without creating a new stream.

The stream terminates when there are no more tickets to process in the queue, or an error is encountered.

Source§

fn neglect_tickets( &self, channel_id: &ChannelId, up_to_index: Option<u64>, ) -> Result<Vec<VerifiedTicket>, TicketManagerError>

Removes all the tickets in the given [ChannelId], optionally only up to the given ticket index (inclusive).

If the up_to_index is given and lower than the lowest index of an unredeemed ticket in the queue, the function does nothing.

If there’s ticket redemption ongoing in the same channel and the neglection intersects with the redeemed range, the redemption will be cut short, with remaining unredeemed tickets neglected.

Source§

fn ticket_stats( &self, channel: Option<&ChannelId>, ) -> Result<ChannelStats, TicketManagerError>

Computes statistics for the given channel or for all channels if None is given.

If the given channel does not exist, it returns zero statistics instead of an error.

Apart from unredeemed_value, the statistics are not persistent.

Source§

type Error = TicketManagerError

Source§

fn insert_incoming_ticket( &self, ticket: RedeemableTicket, ) -> Result<Vec<VerifiedTicket>, TicketManagerError>

Inserts an incoming winning ticket into the management queue. Read more

Auto Trait Implementations§

§

impl<S, Q> Freeze for HoprTicketManager<S, Q>

§

impl<S, Q> !RefUnwindSafe for HoprTicketManager<S, Q>

§

impl<S, Q> Send for HoprTicketManager<S, Q>
where S: Send + Sync, Q: Send + Sync,

§

impl<S, Q> Sync for HoprTicketManager<S, Q>
where S: Send + Sync, Q: Send + Sync,

§

impl<S, Q> Unpin for HoprTicketManager<S, Q>

§

impl<S, Q> !UnwindSafe for HoprTicketManager<S, Q>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
§

impl<T> Pointable for T

§

const ALIGN: usize

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
§

impl<T> PolicyExt for T
where T: ?Sized,

§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] only if self and other return Action::Follow. Read more
§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
§

impl<T> TicketManagementExt for T
where T: TicketManagement + ?Sized,

§

fn redeem_in_channels<'life0, 'async_trait, C>( &'life0 self, client: C, selector: Option<ChannelSelector>, min_amount: Option<Balance<WxHOPR>>, min_grace_period: Option<Duration>, ) -> Pin<Box<dyn Future<Output = Result<impl Stream<Item = Result<RedemptionResult, Self::Error>> + Send, <C as ChainReadChannelOperations>::Error>> + Send + 'async_trait>>
where 'life0: 'async_trait, C: ChainReadChannelOperations + ChainWriteTicketOperations + Clone + Send + Sync + 'static + 'async_trait, Self: Sync + 'async_trait,

Performs redemptions in multiple channels. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more