Signer Cache Expiry for All Chains
Summary
Extends the Solana signer cache expiry pattern (MR !4759 (merged)) to all remaining chain clients (UTXO, EVM, Cosmos, TRON, XRP).
When a broadcast tx is dropped from the mempool, the signer cache previously blocked re-signing indefinitely — requiring operators on every vault member to manually clear the cache. Now, cache entries use SetSignedWithExpiry with a configurable expiry (default 72h). After expiry, bypass requires both:
- The operational mimir
SkipSignerCache<Chain>to be set - On-chain verification confirming the broadcast tx is absent
This two-gate model prevents double-spend on chains where signed transactions remain valid indefinitely, while allowing operators to unstick outbounds via a single mimir vote instead of coordinated cache clearing across all vault members.
Changes
constants/mimir_strings.go— AddSkipSignerCache%smimir templateconfig/config.go— AddSignerCacheExpiryfield toBifrostChainConfiguration(default 72h)bifrost/pkg/chainclients/utxo/signer.go—HasSignedWithExpiry+ mimir gate +GetRawTransactionVerboseverificationbifrost/pkg/chainclients/evm/client.go—HasSignedWithExpiry+ mimir gate +TransactionReceiptverificationbifrost/pkg/chainclients/gaia/cosmos_client.go—HasSignedWithExpiry+ mimir gate + gRPCGetTxverificationbifrost/pkg/chainclients/tron/tron_client.go—HasSignedWithExpiry+ mimir gate +GetTransactionInfoverificationbifrost/pkg/chainclients/xrp/client.go—HasSignedWithExpiry+ mimir gate + XRPtxRPC verification
Context
A set of BTC outbounds was broadcast, dropped from mempool, and then stuck indefinitely because the signer cache blocked re-signing. The immediate fix required coordinated cache clearing across all vault members. This MR makes future occurrences recoverable via a mimir vote (SkipSignerCacheBTC=1), set temporarily until the outbound clears.
Test Plan
- Signer cache unit tests pass (
./bifrost/pkg/chainclients/shared/signercache/...) - All chain client tests pass (UTXO, EVM, GAIA, TRON, XRP)
- Full build passes
- Verify on stagenet: set
SkipSignerCache<Chain>mimir, confirm expired cache entries are bypassed after on-chain verification