Skip to main content

Storage

Trait Storage 

Source
pub trait Storage {
Show 36 methods // Required methods fn insert_output<'life0, 'life1, 'async_trait>( &'life0 self, output: &'life1 Output, ) -> Pin<Box<dyn Future<Output = Result<(), StorageError>> + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait; fn insert_output_with_origin<'life0, 'life1, 'async_trait>( &'life0 self, output: &'life1 Output, gasp: bool, ) -> Pin<Box<dyn Future<Output = Result<(), StorageError>> + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait; fn delete_output<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, txid: &'life1 str, output_index: u32, topic: &'life2 str, ) -> Pin<Box<dyn Future<Output = Result<(), StorageError>> + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait; fn mark_utxo_as_spent<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, txid: &'life1 str, output_index: u32, topic: &'life2 str, ) -> Pin<Box<dyn Future<Output = Result<(), StorageError>> + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait; fn update_consumed_by<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, txid: &'life1 str, output_index: u32, topic: &'life2 str, consumed_by: &'life3 [Outpoint], ) -> Pin<Box<dyn Future<Output = Result<(), StorageError>> + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait; fn update_transaction_beef<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, txid: &'life1 str, beef: &'life2 [u8], ) -> Pin<Box<dyn Future<Output = Result<(), StorageError>> + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait; fn insert_applied_transaction<'life0, 'life1, 'async_trait>( &'life0 self, tx: &'life1 AppliedTransaction, ) -> Pin<Box<dyn Future<Output = Result<(), StorageError>> + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait; fn does_applied_transaction_exist<'life0, 'life1, 'async_trait>( &'life0 self, tx: &'life1 AppliedTransaction, ) -> Pin<Box<dyn Future<Output = Result<bool, StorageError>> + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait; fn delete_applied_transaction<'life0, 'life1, 'async_trait>( &'life0 self, tx: &'life1 AppliedTransaction, ) -> Pin<Box<dyn Future<Output = Result<(), StorageError>> + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait; fn find_output<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, txid: &'life1 str, output_index: u32, topic: Option<&'life2 str>, spent: Option<bool>, include_beef: bool, ) -> Pin<Box<dyn Future<Output = Result<Option<Output>, StorageError>> + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait; fn find_outputs_for_transaction<'life0, 'life1, 'async_trait>( &'life0 self, txid: &'life1 str, include_beef: bool, ) -> Pin<Box<dyn Future<Output = Result<Vec<Output>, StorageError>> + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait; fn find_utxos_for_topic<'life0, 'life1, 'async_trait>( &'life0 self, topic: &'life1 str, since: Option<f64>, limit: Option<u64>, include_beef: bool, ) -> Pin<Box<dyn Future<Output = Result<Vec<Output>, StorageError>> + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait; fn update_last_interaction<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, host: &'life1 str, topic: &'life2 str, since: u64, ) -> Pin<Box<dyn Future<Output = Result<(), StorageError>> + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait; fn get_last_interaction<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, host: &'life1 str, topic: &'life2 str, ) -> Pin<Box<dyn Future<Output = Result<u64, StorageError>> + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait; fn record_peer_sync_outcome<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, host: &'life1 str, topic: &'life2 str, success: bool, ) -> Pin<Box<dyn Future<Output = Result<(), StorageError>> + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait; fn get_peer_sync_health<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, host: &'life1 str, topic: &'life2 str, ) -> Pin<Box<dyn Future<Output = Result<PeerSyncHealth, StorageError>> + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait; fn record_peer_sync_yield<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, host: &'life1 str, topic: &'life2 str, yielded: bool, ) -> Pin<Box<dyn Future<Output = Result<PeerYieldStreak, StorageError>> + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait; fn put_deferred_graph<'life0, 'life1, 'async_trait>( &'life0 self, record: &'life1 DeferredGraph, ) -> Pin<Box<dyn Future<Output = Result<DeferredGraphSave, StorageError>> + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait; fn reserve_unanchorable_retry<'life0, 'life1, 'async_trait>( &'life0 self, record: &'life1 DeferredGraph, ) -> Pin<Box<dyn Future<Output = Result<bool, StorageError>> + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait; fn read_fault_memos<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, host: &'life1 str, topic: &'life2 str, outpoints: Option<&'life3 [String]>, ) -> Pin<Box<dyn Future<Output = Result<FaultMemoBatch, StorageError>> + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait; fn find_deferred_graphs<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, host: &'life1 str, topic: &'life2 str, ) -> Pin<Box<dyn Future<Output = Result<Vec<DeferredGraphKey>, StorageError>> + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait; fn get_deferred_graph<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, host: &'life1 str, topic: &'life2 str, outpoint: &'life3 str, ) -> Pin<Box<dyn Future<Output = Result<Option<DeferredGraph>, StorageError>> + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait; fn delete_deferred_graph<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, host: &'life1 str, topic: &'life2 str, outpoint: &'life3 str, ) -> Pin<Box<dyn Future<Output = Result<(), StorageError>> + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait; // Provided methods fn mark_transaction_proven<'life0, 'life1, 'async_trait>( &'life0 self, txid: &'life1 str, ) -> Pin<Box<dyn Future<Output = Result<(), StorageError>> + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait { ... } fn mark_transaction_proven_at<'life0, 'life1, 'async_trait>( &'life0 self, txid: &'life1 str, height: Option<u64>, ) -> Pin<Box<dyn Future<Output = Result<(), StorageError>> + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait { ... } fn update_output_block_height<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, txid: &'life1 str, output_index: u32, topic: &'life2 str, block_height: u32, ) -> Pin<Box<dyn Future<Output = Result<(), StorageError>> + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait { ... } fn find_outputs_by_outpoints<'life0, 'life1, 'async_trait>( &'life0 self, outpoints: &'life1 [Outpoint], include_beef: bool, ) -> Pin<Box<dyn Future<Output = Result<Vec<Output>, StorageError>> + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait { ... } fn find_served_outputs<'life0, 'life1, 'async_trait>( &'life0 self, outpoints: &'life1 [Outpoint], ) -> Pin<Box<dyn Future<Output = Result<Vec<Output>, StorageError>> + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait { ... } fn find_transactions_for_proof_check<'life0, 'async_trait>( &'life0 self, limit: u64, min_age_secs: u64, ) -> Pin<Box<dyn Future<Output = Result<Vec<TransactionBeef>, StorageError>> + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait { ... } fn get_peer_cadence<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, _host: &'life1 str, _topic: &'life2 str, ) -> Pin<Box<dyn Future<Output = Result<PeerCadence, StorageError>> + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait { ... } fn set_peer_cadence<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, _host: &'life1 str, _topic: &'life2 str, _state: &'life3 PeerCadence, ) -> Pin<Box<dyn Future<Output = Result<(), StorageError>> + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait { ... } fn remember_expired_outpoint<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, _topic: &'life1 str, _outpoint: &'life2 str, _expiry: u64, ) -> Pin<Box<dyn Future<Output = Result<(), StorageError>> + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait { ... } fn find_expired_outpoints<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, _topic: &'life1 str, _outpoints: &'life2 [String], ) -> Pin<Box<dyn Future<Output = Result<Vec<String>, StorageError>> + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait { ... } fn write_batch<'life0, 'life1, 'async_trait>( &'life0 self, writes: &'life1 [PageWrite], ) -> Pin<Box<dyn Future<Output = Result<u64, StorageError>> + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait { ... } fn find_topic_outputs<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, topic: &'life1 str, outpoints: &'life2 [(String, u32)], ) -> Pin<Box<dyn Future<Output = Result<Vec<Output>, StorageError>> + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait { ... } fn find_applied_transactions<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, topic: &'life1 str, txids: &'life2 [String], ) -> Pin<Box<dyn Future<Output = Result<Vec<String>, StorageError>> + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait { ... }
}
Expand description

Overlay Services storage backend.

All methods are async. Uses ?Send futures for wasm32 compatibility (Cloudflare Workers D1).

Required Methods§

Source

fn insert_output<'life0, 'life1, 'async_trait>( &'life0 self, output: &'life1 Output, ) -> Pin<Box<dyn Future<Output = Result<(), StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Insert a new output into storage.

If an output with the same (txid, outputIndex, topic) already exists, this is a no-op. If output.beef is Some, also upsert the BEEF into the transactions table (deduplicated by txid).

Source

fn insert_output_with_origin<'life0, 'life1, 'async_trait>( &'life0 self, output: &'life1 Output, gasp: bool, ) -> Pin<Box<dyn Future<Output = Result<(), StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Insert an output and record its admission origin with its transaction. A GASP finalization has no broadcaster callback to wait for. Wrappers must forward this method; ordinary submissions pass false.

Source

fn delete_output<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, txid: &'life1 str, output_index: u32, topic: &'life2 str, ) -> Pin<Box<dyn Future<Output = Result<(), StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Delete an output from storage.

After deletion, if no other outputs reference the same txid, also delete the transaction’s BEEF from the transactions table.

Source

fn mark_utxo_as_spent<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, txid: &'life1 str, output_index: u32, topic: &'life2 str, ) -> Pin<Box<dyn Future<Output = Result<(), StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Mark an output as spent.

Source

fn update_consumed_by<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, txid: &'life1 str, output_index: u32, topic: &'life2 str, consumed_by: &'life3 [Outpoint], ) -> Pin<Box<dyn Future<Output = Result<(), StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait,

Update the consumed_by list on an existing output.

Source

fn update_transaction_beef<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, txid: &'life1 str, beef: &'life2 [u8], ) -> Pin<Box<dyn Future<Output = Result<(), StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Update the BEEF data for a transaction (used when merkle proofs arrive).

Source

fn insert_applied_transaction<'life0, 'life1, 'async_trait>( &'life0 self, tx: &'life1 AppliedTransaction, ) -> Pin<Box<dyn Future<Output = Result<(), StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Record that a transaction has been applied to a topic (deduplication).

Source

fn does_applied_transaction_exist<'life0, 'life1, 'async_trait>( &'life0 self, tx: &'life1 AppliedTransaction, ) -> Pin<Box<dyn Future<Output = Result<bool, StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Check if a transaction has already been applied to a topic.

Source

fn delete_applied_transaction<'life0, 'life1, 'async_trait>( &'life0 self, tx: &'life1 AppliedTransaction, ) -> Pin<Box<dyn Future<Output = Result<(), StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

bsv-low PLAN-PRE-LOOP4 §H4 (2026-09-06): forget a (txid, topic) applied record so a re-submit of those bytes is re-validated instead of deduplicated away. The caller proves the row is PHANTOM (no stored output of that txid on that topic) before asking — see Engine::forget_phantom_applied.

Source

fn find_output<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, txid: &'life1 str, output_index: u32, topic: Option<&'life2 str>, spent: Option<bool>, include_beef: bool, ) -> Pin<Box<dyn Future<Output = Result<Option<Output>, StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Find a single output by txid + outputIndex, with optional topic and spent filters.

If include_beef is true, load the BEEF from the transactions table and attach it to the returned Output.

Source

fn find_outputs_for_transaction<'life0, 'life1, 'async_trait>( &'life0 self, txid: &'life1 str, include_beef: bool, ) -> Pin<Box<dyn Future<Output = Result<Vec<Output>, StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Find all outputs for a given transaction.

Source

fn find_utxos_for_topic<'life0, 'life1, 'async_trait>( &'life0 self, topic: &'life1 str, since: Option<f64>, limit: Option<u64>, include_beef: bool, ) -> Pin<Box<dyn Future<Output = Result<Vec<Output>, StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Find unspent outputs for a topic, ordered by score ascending.

  • since: minimum score threshold (exclusive of scores below this)
  • limit: maximum number of results
Source

fn update_last_interaction<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, host: &'life1 str, topic: &'life2 str, since: u64, ) -> Pin<Box<dyn Future<Output = Result<(), StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Update the last interaction score for a host+topic pair (upsert).

Source

fn get_last_interaction<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, host: &'life1 str, topic: &'life2 str, ) -> Pin<Box<dyn Future<Output = Result<u64, StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Get the last interaction score for a host+topic pair. Returns 0 if not found.

Source

fn record_peer_sync_outcome<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, host: &'life1 str, topic: &'life2 str, success: bool, ) -> Pin<Box<dyn Future<Output = Result<(), StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Record the outcome of ONE GASP sync attempt with host for topic (bsv-low#302). success = true resets the consecutive-failure count to 0 (full re-admission); false increments it. The backend stamps its own clock for the attempt time — the engine never supplies wall time. Quarantine-SKIPPED peers are NOT recorded (a skip is not an attempt; the last-attempt age must keep growing so the re-probe window opens). Nor is, with a per-graph budget, a sync of a peer at the quarantine threshold that did not fail and yielded nothing (bsv-low #555, the delta-4 fold’s D4-L2): only a yield re-admits that peer.

Source

fn get_peer_sync_health<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, host: &'life1 str, topic: &'life2 str, ) -> Pin<Box<dyn Future<Output = Result<PeerSyncHealth, StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Current sync health of the (host, topic) pairing (bsv-low#302). The backend answers with its consecutive-failure count and the AGE of the last attempt (relative seconds, so the engine needs no clock of its own). Pristine: never attempted, never quarantined.

Source

fn record_peer_sync_yield<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, host: &'life1 str, topic: &'life2 str, yielded: bool, ) -> Pin<Box<dyn Future<Output = Result<PeerYieldStreak, StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Record whether ONE GASP sync with host for topic YIELDED (it finalized a graph or moved the cursor) or not, and answer the yieldless STREAK it now holds (bsv-low #555, the delta fold’s D-M2 and the delta-2 fold’s D2-M1; crate::gasp::yieldless_sync_failed):

  • true ends the streak: count 0, no start; answers that.
  • false adds one to the streak and answers its count and the seconds since its FIRST yieldless sync, on the backend’s own clock (0 on the sync that starts it). A streak whose LAST yieldless sync is more than crate::gasp::PEER_YIELDLESS_DECAY_SECS old starts again (count 1, age 0): the decay. NOT for a peer whose Self::record_peer_sync_outcome count is above 0 (the delta-3 fold’s D3-M1): the decay equals the reprobe window, so a quarantined peer’s probe would start a fresh streak, succeed and lift the quarantine; its probe continues the streak instead and fails.

The engine calls it only with a per-graph budget, only for a sync the peer served work, and before Self::record_peer_sync_outcome.

Source

fn put_deferred_graph<'life0, 'life1, 'async_trait>( &'life0 self, record: &'life1 DeferredGraph, ) -> Pin<Box<dyn Future<Output = Result<DeferredGraphSave, StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Save (REPLACE) the record of one deferred GASP graph, keyed by (record.peer, record.topic, record.outpoint). One row per graph: a later deferral of the same graph overwrites it, never appends. AtCeiling: refused at a bound of the storage’s own (the worker’s global ceiling), counted too_many; the walk then goes on under the per-peer budget alone, as before #555.

The deferred-graph methods are REQUIRED (the lens fold’s M2, the house style of TopicManager::identify_admissible_outputs): with a default, a storage or WRAPPER that did not forward them compiled, and Engine::set_graph_budget over it saved nothing, walked every graph past the call budget from its root on every tick and never admitted it (store_fault), a hard cap on graph size worse than no budget. A wrapper forwards these methods to the storage it wraps:

ⓘ
async fn put_deferred_graph(&self, record: &DeferredGraph)
    -> Result<DeferredGraphSave, StorageError> {
    self.inner.put_deferred_graph(record).await
}
// and the same for find_deferred_graphs, get_deferred_graph and
// delete_deferred_graph and reserve_unanchorable_retry.

A backend that keeps no records answers none from find_deferred_graphs and get_deferred_graph and an Err from this one: every graph past the budget then fails its UTXO, so it must not be given a per-graph budget.

Source

fn reserve_unanchorable_retry<'life0, 'life1, 'async_trait>( &'life0 self, record: &'life1 DeferredGraph, ) -> Pin<Box<dyn Future<Output = Result<bool, StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Atomically replace an unanchorable record only when its score and class match, its backoff elapsed, and record reserves exactly the next retry. Return false on a stale claim or exhausted room. Wrappers must forward it.

Source

fn read_fault_memos<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, host: &'life1 str, topic: &'life2 str, outpoints: Option<&'life3 [String]>, ) -> Pin<Box<dyn Future<Output = Result<FaultMemoBatch, StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait,

Read compact fault facts. With a page, use only its outpoint keys. With None, atomically fold legacy fault records out of partial-graph storage, sweep expired facts, and return at most FAULT_MEMO_DUE_LIMIT due records. The legacy graph accessors also address memo facts, while find_deferred_graphs enumerates partial graphs only.

Source

fn find_deferred_graphs<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, host: &'life1 str, topic: &'life2 str, ) -> Pin<Box<dyn Future<Output = Result<Vec<DeferredGraphKey>, StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

The KEYS of the records of (host, topic), lowest score first. A sync reads these up front and each record only when its UTXO is served (the lens fold’s L3).

Source

fn get_deferred_graph<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, host: &'life1 str, topic: &'life2 str, outpoint: &'life3 str, ) -> Pin<Box<dyn Future<Output = Result<Option<DeferredGraph>, StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait,

The record of the graph of (host, topic) rooted at outpoint.

Source

fn delete_deferred_graph<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, host: &'life1 str, topic: &'life2 str, outpoint: &'life3 str, ) -> Pin<Box<dyn Future<Output = Result<(), StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait,

Delete the record of the graph rooted at outpoint.

Provided Methods§

Source

fn mark_transaction_proven<'life0, 'life1, 'async_trait>( &'life0 self, txid: &'life1 str, ) -> Pin<Box<dyn Future<Output = Result<(), StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Mark a transaction as already carrying its own merkle proof, WITHOUT rewriting its BEEF.

This is the lightweight flag-flip used by Engine::complete_missing_proofs when a scanned candidate turns out to ALREADY be proven (its stored BEEF proves the target tx) yet its backend has_proof flag is still 0 — e.g. a GASP-synced tx that arrived with a proof, written before overlay migration 0010 added the flag (the migration defaulted every existing row to 0). Such rows are returned by Storage::find_transactions_for_proof_check every tick and skipped by the engine, clogging the candidate window and starving genuinely proofless rows behind them. Flipping the flag here drops them out.

The reference D1 backend runs UPDATE transactions SET has_proof = 1 WHERE txid = ?. Backends that do not track a proof flag may use this no-op default. Idempotent.

Source

fn mark_transaction_proven_at<'life0, 'life1, 'async_trait>( &'life0 self, txid: &'life1 str, height: Option<u64>, ) -> Pin<Box<dyn Future<Output = Result<(), StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Self::mark_transaction_proven that ALSO records the block height the just-verified bump anchors the tx to (proofHeight, bsv-low M19 R2 round 3 review MED-2), so the revalidation sweep’s transactions leg can window the row. None records no anchor. Default: the plain latch (a backend without the column loses only the windowing, never correctness).

Source

fn update_output_block_height<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, txid: &'life1 str, output_index: u32, topic: &'life2 str, block_height: u32, ) -> Pin<Box<dyn Future<Output = Result<(), StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Update the block height on an output (when it gets mined).

Optional — backends that don’t track block height can provide a no-op default.

Source

fn find_outputs_by_outpoints<'life0, 'life1, 'async_trait>( &'life0 self, outpoints: &'life1 [Outpoint], include_beef: bool, ) -> Pin<Box<dyn Future<Output = Result<Vec<Output>, StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Batch-find outputs by outpoints. More efficient than individual find_output calls.

Default implementation falls back to individual lookups.

Source

fn find_served_outputs<'life0, 'life1, 'async_trait>( &'life0 self, outpoints: &'life1 [Outpoint], ) -> Pin<Box<dyn Future<Output = Result<Vec<Output>, StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Lookup-only read. Backends with observation stamps apply the shared proof window here, before returning BEEF. Internal graph reads remain available.

Source

fn find_transactions_for_proof_check<'life0, 'async_trait>( &'life0 self, limit: u64, min_age_secs: u64, ) -> Pin<Box<dyn Future<Output = Result<Vec<TransactionBeef>, StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Return a bounded page of proofless stored transactions (txid + BEEF bytes) for proof-completion scanning.

Backends MUST return only transactions whose own merkle proof is still missing — i.e. the historical/recent backlog the Engine::complete_missing_proofs cron is meant to clear. The reference D1 backend keeps a has_proof flag (overlay migration 0010), set on every BEEF write, and answers this with WHERE has_proof = 0 LIMIT {limit} — so every proofless tx is eventually reached (no “newest N rows only” starvation) and proven rows are never re-fetched. The engine still defensively re-parses each returned BEEF and skips any that turn out already-proven, so an over-inclusive backend is merely less efficient, not incorrect.

Backends that cannot enumerate transactions (or have nothing to complete) may return an empty Vec via this default, in which case proof completion is a no-op.

limit bounds the returned page (and therefore the per-tick WoC fetch / CPU budget).

min_age_secs is the PUSH-PRIMARY BACKSTOP gate (bsv-low #228 / arcade#259): rows stored less than min_age_secs ago are EXCLUDED — their proof is expected to arrive via the Arcade MINED webhook (/arc-ingest) at push speed, so polling them is wasted budget. Rules:

  • 0 disables the gate (poll everything — today’s behaviour).
  • a row whose age is UNKNOWN (pre-migration NULL timestamp) MUST be treated as OLD, i.e. eligible — the fail-safe direction is to poll MORE, never to starve a row of its backstop. The reference D1 backend answers with AND (created_at IS NULL OR created_at <= unixepoch() - min_age_secs).
Source

fn get_peer_cadence<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, _host: &'life1 str, _topic: &'life2 str, ) -> Pin<Box<dyn Future<Output = Result<PeerCadence, StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Optional load control. An older backend stays eligible on every run.

Source

fn set_peer_cadence<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, _host: &'life1 str, _topic: &'life2 str, _state: &'life3 PeerCadence, ) -> Pin<Box<dyn Future<Output = Result<(), StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait,

Source

fn remember_expired_outpoint<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, _topic: &'life1 str, _outpoint: &'life2 str, _expiry: u64, ) -> Pin<Box<dyn Future<Output = Result<(), StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Remember that the GASP walk refused outpoint of topic because its own advert had expired at expiry (unix seconds, read from the output’s bytes bound to its txid, never a peer’s word). The backend keeps the row until max(expiry, now) + crate::gasp::EXPIRED_OUTPOINT_MEMO_SECS on its own clock and at most crate::gasp::EXPIRED_OUTPOINT_MEMO_MAX_ROWS rows a topic, so a later sync skips it with no node fetch.

Defaulted, unlike the deferred-graph methods: a backend or wrapper that does not forward these is fail-safe, the walk fetches and refuses the dead again each run as it did before 0.1.8. A wrapper forwards both all the same.

Source

fn find_expired_outpoints<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, _topic: &'life1 str, _outpoints: &'life2 [String], ) -> Pin<Box<dyn Future<Output = Result<Vec<String>, StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Of outpoints, those of topic remembered as expired and not yet swept (see Self::remember_expired_outpoint).

Source

fn write_batch<'life0, 'life1, 'async_trait>( &'life0 self, writes: &'life1 [PageWrite], ) -> Pin<Box<dyn Future<Output = Result<u64, StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Apply a GASP page’s writes as ONE unit, in order, and answer the statements it ran. A backend that can make it atomic should (D1’s batch()); this default applies them one at a time and stops at the earliest fault, which is safe because every page write is idempotent and the engine keeps the whole page queued until this answers Ok. A crate::page_batch::PageWrite::Backend statement belongs to the backend that deferred it: a backend that defers none never sees one, and this default refuses it.

Source

fn find_topic_outputs<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, topic: &'life1 str, outpoints: &'life2 [(String, u32)], ) -> Pin<Box<dyn Future<Output = Result<Vec<Output>, StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Of outpoints ((txid, output_index)), the outputs held in topic, without BEEF, spent or not: find_output(txid, vout, Some(topic), None, false) for a page at once. Default: one read each.

Source

fn find_applied_transactions<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, topic: &'life1 str, txids: &'life2 [String], ) -> Pin<Box<dyn Future<Output = Result<Vec<String>, StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Of txids, those with an applied row in topic. Default: one read each.

Dyn Compatibility§

This trait is dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementations on Foreign Types§

Source§

impl<T: Storage + ?Sized> Storage for Rc<T>

Delegating impl so an Rc<T: Storage> is itself a Storage — lets a caller keep a shared handle to the concrete backend (e.g. a test advancing [memory::MemoryStorage::advance_clock]) while the engine owns a Box<dyn Storage> over the same instance. Pure delegation, no semantics.

Source§

fn write_batch<'life0, 'life1, 'async_trait>( &'life0 self, writes: &'life1 [PageWrite], ) -> Pin<Box<dyn Future<Output = Result<u64, StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Source§

fn find_topic_outputs<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, topic: &'life1 str, outpoints: &'life2 [(String, u32)], ) -> Pin<Box<dyn Future<Output = Result<Vec<Output>, StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Source§

fn find_applied_transactions<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, topic: &'life1 str, txids: &'life2 [String], ) -> Pin<Box<dyn Future<Output = Result<Vec<String>, StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Source§

fn insert_output_with_origin<'life0, 'life1, 'async_trait>( &'life0 self, output: &'life1 Output, gasp: bool, ) -> Pin<Box<dyn Future<Output = Result<(), StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Source§

fn read_fault_memos<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, host: &'life1 str, topic: &'life2 str, outpoints: Option<&'life3 [String]>, ) -> Pin<Box<dyn Future<Output = Result<FaultMemoBatch, StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait,

Source§

fn get_peer_cadence<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, host: &'life1 str, topic: &'life2 str, ) -> Pin<Box<dyn Future<Output = Result<PeerCadence, StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Source§

fn set_peer_cadence<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, host: &'life1 str, topic: &'life2 str, state: &'life3 PeerCadence, ) -> Pin<Box<dyn Future<Output = Result<(), StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait,

Source§

fn insert_output<'life0, 'life1, 'async_trait>( &'life0 self, output: &'life1 Output, ) -> Pin<Box<dyn Future<Output = Result<(), StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Source§

fn delete_output<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, txid: &'life1 str, output_index: u32, topic: &'life2 str, ) -> Pin<Box<dyn Future<Output = Result<(), StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Source§

fn mark_utxo_as_spent<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, txid: &'life1 str, output_index: u32, topic: &'life2 str, ) -> Pin<Box<dyn Future<Output = Result<(), StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Source§

fn update_consumed_by<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, txid: &'life1 str, output_index: u32, topic: &'life2 str, consumed_by: &'life3 [Outpoint], ) -> Pin<Box<dyn Future<Output = Result<(), StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait,

Source§

fn update_transaction_beef<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, txid: &'life1 str, beef: &'life2 [u8], ) -> Pin<Box<dyn Future<Output = Result<(), StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Source§

fn mark_transaction_proven<'life0, 'life1, 'async_trait>( &'life0 self, txid: &'life1 str, ) -> Pin<Box<dyn Future<Output = Result<(), StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Source§

fn mark_transaction_proven_at<'life0, 'life1, 'async_trait>( &'life0 self, txid: &'life1 str, height: Option<u64>, ) -> Pin<Box<dyn Future<Output = Result<(), StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Source§

fn update_output_block_height<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, txid: &'life1 str, output_index: u32, topic: &'life2 str, block_height: u32, ) -> Pin<Box<dyn Future<Output = Result<(), StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Source§

fn insert_applied_transaction<'life0, 'life1, 'async_trait>( &'life0 self, tx: &'life1 AppliedTransaction, ) -> Pin<Box<dyn Future<Output = Result<(), StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Source§

fn does_applied_transaction_exist<'life0, 'life1, 'async_trait>( &'life0 self, tx: &'life1 AppliedTransaction, ) -> Pin<Box<dyn Future<Output = Result<bool, StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Source§

fn delete_applied_transaction<'life0, 'life1, 'async_trait>( &'life0 self, tx: &'life1 AppliedTransaction, ) -> Pin<Box<dyn Future<Output = Result<(), StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Source§

fn find_output<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, txid: &'life1 str, output_index: u32, topic: Option<&'life2 str>, spent: Option<bool>, include_beef: bool, ) -> Pin<Box<dyn Future<Output = Result<Option<Output>, StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Source§

fn find_served_outputs<'life0, 'life1, 'async_trait>( &'life0 self, outpoints: &'life1 [Outpoint], ) -> Pin<Box<dyn Future<Output = Result<Vec<Output>, StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Source§

fn find_outputs_for_transaction<'life0, 'life1, 'async_trait>( &'life0 self, txid: &'life1 str, include_beef: bool, ) -> Pin<Box<dyn Future<Output = Result<Vec<Output>, StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Source§

fn find_utxos_for_topic<'life0, 'life1, 'async_trait>( &'life0 self, topic: &'life1 str, since: Option<f64>, limit: Option<u64>, include_beef: bool, ) -> Pin<Box<dyn Future<Output = Result<Vec<Output>, StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Source§

fn find_transactions_for_proof_check<'life0, 'async_trait>( &'life0 self, limit: u64, min_age_secs: u64, ) -> Pin<Box<dyn Future<Output = Result<Vec<TransactionBeef>, StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Source§

fn update_last_interaction<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, host: &'life1 str, topic: &'life2 str, since: u64, ) -> Pin<Box<dyn Future<Output = Result<(), StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Source§

fn get_last_interaction<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, host: &'life1 str, topic: &'life2 str, ) -> Pin<Box<dyn Future<Output = Result<u64, StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Source§

fn record_peer_sync_outcome<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, host: &'life1 str, topic: &'life2 str, success: bool, ) -> Pin<Box<dyn Future<Output = Result<(), StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Source§

fn get_peer_sync_health<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, host: &'life1 str, topic: &'life2 str, ) -> Pin<Box<dyn Future<Output = Result<PeerSyncHealth, StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Source§

fn record_peer_sync_yield<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, host: &'life1 str, topic: &'life2 str, yielded: bool, ) -> Pin<Box<dyn Future<Output = Result<PeerYieldStreak, StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Source§

fn put_deferred_graph<'life0, 'life1, 'async_trait>( &'life0 self, record: &'life1 DeferredGraph, ) -> Pin<Box<dyn Future<Output = Result<DeferredGraphSave, StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Source§

fn reserve_unanchorable_retry<'life0, 'life1, 'async_trait>( &'life0 self, record: &'life1 DeferredGraph, ) -> Pin<Box<dyn Future<Output = Result<bool, StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Source§

fn find_deferred_graphs<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, host: &'life1 str, topic: &'life2 str, ) -> Pin<Box<dyn Future<Output = Result<Vec<DeferredGraphKey>, StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Source§

fn get_deferred_graph<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, host: &'life1 str, topic: &'life2 str, outpoint: &'life3 str, ) -> Pin<Box<dyn Future<Output = Result<Option<DeferredGraph>, StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait,

Source§

fn delete_deferred_graph<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, host: &'life1 str, topic: &'life2 str, outpoint: &'life3 str, ) -> Pin<Box<dyn Future<Output = Result<(), StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait,

Source§

fn remember_expired_outpoint<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, topic: &'life1 str, outpoint: &'life2 str, expiry: u64, ) -> Pin<Box<dyn Future<Output = Result<(), StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Source§

fn find_expired_outpoints<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, topic: &'life1 str, outpoints: &'life2 [String], ) -> Pin<Box<dyn Future<Output = Result<Vec<String>, StorageError>> + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Implementors§