pub trait ActionHandler {
    fn check_stateless<'life0, 'async_trait>(
        &'life0 self,
        context: Arc<Transaction>
    ) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
    where
        Self: 'async_trait,
        'life0: 'async_trait
; fn check_stateful<'life0, 'async_trait>(
        &'life0 self,
        state: Arc<State>
    ) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
    where
        Self: 'async_trait,
        'life0: 'async_trait
; fn execute<'life0, 'life1, 'async_trait>(
        &'life0 self,
        state: &'life1 mut StateTransaction<'_>
    ) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
    where
        Self: 'async_trait,
        'life0: 'async_trait,
        'life1: 'async_trait
; }
Expand description

Defines the interface for handling transaction actions.

Block-wide execution is performed using the Component trait. Per-transaction execution is performed using the ActionHandler trait.

The ActionHandler trait has a top-level implementation on Transaction, which performs any transaction-wide checks and then calls the ActionHandler implementation for each Action.

The validation logic in the ActionHandler trait is split into three phases:

All of these methods are asynchronous and fallible; an error at any level fails the transaction and aborts any in-progress execution.

These methods are described in more detail below, but in general, as much work as possible should be pushed up the stack, where greater parallelism is available, with checks performed in execute only as a last resort.

Required Methods§

Performs all of this action’s stateless validity checks in the context of some Transaction.

This method is async to make it easy to perform stateless validity checks in parallel, by allowing ActionHandler implementations to easily spawn tasks internally.

Supplying the context means that stateless checks can use transaction-wide data like the SCT anchor. Supplying it as an Arc<Transaction> makes it easy to share the context with internally spawned tasks.

As much work as possible should be done in check_stateless, as it can be run in parallel across all transactions in a block.

Performs all of this action’s stateful validity checks.

This method provides read access to a snapshot of the State prior to transaction execution. Because it does not give write access, it’s safe to run the ActionHandler implementations for all actions in a given transaction in parallel.

As much work as possible should be done in check_stateful, as it can be run in parallel across all actions within a transaction.

Invariants

This method should only be called on data that has been checked with ActionHandler::check_stateless. This method can be called before Component::begin_block.

Attempts to execute this action against the provided state.

This method provides read and write access to the state. It is fallible, so it’s possible to perform checks within the execute implementation and abort execution on error; the StateTransaction mechanism ensures that all writes are correctly discarded.

Because execute must run sequentially, whenever possible, checks should be performed in ActionHandler::check_stateful or ActionHandler::check_stateless. One example of where this is not possible (in fact, the motivating example) is for IBC, where a transaction may (1) submit a client update and then (2) relay messages valid relative to the newly updated state. In this case, the checks for (2) must be performed during execution, as they depend on the state changes written while processing the client update.

However, this data flow pattern should be avoided whenever possible.

Invariants

This method should only be called immediately after an invocation of ActionHandler::check_stateful on the same transaction. This method can be called before Component::begin_block.

Implementations on Foreign Types§

Debits an opened position NFT and credits a closed position NFT.

Debits the initial reserves and credits an opened position NFT.

Debits a withdrawn position NFT and credits a claimed position NFT and any liquidity incentives.

Debits a closed position NFT and credits a withdrawn position NFT and the final reserves.

Implementors§