feat(bifrost): SOL vault keep-alive self-sign to keep signature cursors fresh

Problem

When trading is halted or the chain is quiet, organic SOL outbounds stop and the newest signature for a vault address ages out of a non-archival RPC's history retention. The scanner's getSignaturesForAddress until-cursor then anchors to a signature the RPC can no longer resolve (-32020), wedging observation for that vault — the SOL scanner prune-wedge.

Fix

Land one minimal on-chain tx per stale vault so the cursor re-anchors at a recent slot, instead of forcing every node onto archival RPCs.

  • The keep-alive is a TSS-signed vault→self transfer carrying the existing consolidate memo — the same network-sends-to-itself primitive the UTXO clients use for consolidation. Accepted by thornode's ConsolidateHandler without a scheduled TxOutItem, netting the vault record to exactly minus the tx fee via the generic observation paths. No consensus change.
  • Trigger: each vault member evaluates the same chain facts every 5 min (current slot vs the vault's newest signature slot) and derives an identical self-send amount from the newest signature's slot, so TSS keysign parties converge without coordination and each refresh round gets a distinct signer-cache hash.
  • Threshold: the votable SignatureRefreshBlocks mimir (THORChain blocks; unset → 14400 ≈ 1 day; 0 disables).
  • A self-send must list the vault account exactly once or Solana rejects with AccountLoadedTwice, so CreateTx routes ToAddress == vault through a new deduplicated NewSelfTransferTransaction builder (account index 0 as both source and destination).

Scope

Bifrost-only (SOL). Part of the 3.19.4 bifrost-only patch. Durable complement to !4905 (merged) (minContextSlot cursor, merged) for the same prune-wedge class.

 sol_client.go              35 ++-
 sol_keepalive.go          262 +++++
 sol_keepalive_test.go     117 +++++
 types/transaction.go       36 +++
 types/transaction_test.go  41 +++
 constants/mimir_strings.go   4 +

Testing

Merges as part of the 3.19.4 set (!4932 (merged) · !4934 (merged) · !4936 (merged)) and is validated together on stagenet via v3.19.4-rc1 after all three land — this collective stagenet run satisfies Fable's request for a devnet/stagenet validation. Not gated on a separate pre-merge run. Unit coverage: sol_keepalive_test.go, types/transaction_test.go.

Edited by Itzamna

Merge request reports

Loading