Skip to content

Commit 8704226

Browse files
authored
Add SessionPersister trait (payjoin#716)
`SessionPersister` is an alternative to `Persister` designed to persist not just the initial state of a BIP78 type state machine, but the full sequence of state transitions. Its explicit purpose is to allow sessions to be replayed from their event history and to give applications the ability to introspect their session’s progress (payjoin#336). A `SessionPersister` is scoped to a specific BIP78 sender or receiver session. Each session consists of discrete pieces of information obtained during execution called session events. These session events are stored via the `save_event` method. When an application resumes a session, it loads these events into a replayer (not included in this commit) to recover the latest session state. If the type state reaches its terminal state or a fatal error occurs, the session is marked as closed via `close()`. Application developers should **not** interact directly with `SessionPersister`. Instead, they interact indirectly by processing state transition objects. These objects represent the possible outcomes of attempting a state transition, and they must be processed for the type state to advance or terminate. There are six kinds of BIP78 state transition outcomes: * A successful state transition that always progresses. * A transition that may result in a **transient error**. In these cases, the application should retry the session from its current state. These errors originate outside of `rust-payjoin`. E.g an `ImplementationError` triggered when executing an `InputsSeen` closure. * A **fatal transition** that must close the session. These errors are unrecoverable, requiring the fallback transaction to be broadcast. Fatal transitions also include an event to be persisted for auditing purposes and may also contain a transient error. * Transitions that are either fatal or have no result (interpreted as success). This is common for transitions handling responses to BIP78 subdirectory GET requests. * A transition that marks the final, successful state of the type state. * The **initial transition**, which is a special case. If it fails, there is no prior state to retry from and nothing to save or close. State transitions are opaque to the application. Each transition method implements a `save()` function, which internally delegates to the appropriate `InternalPersistedSession` trait method. These internal methods are strongly typed to ensure correctness and are not accessible to the application layer. Only the `save()` methods are exposed. Each `save()` call returns a `Result` indicating either the next state transition (if there is one) or a `PersistedError`, which captures all possible failure modes e.g., `Fatal`, `Transient`, etc.
2 parents a9cef3f + d70d64e commit 8704226

File tree

1 file changed

+988
-0
lines changed

1 file changed

+988
-0
lines changed

0 commit comments

Comments
 (0)