Bifrost: Hold vault lock through broadcast & add RPC context deadlines

Supersedes !4448 (closed).

This is a replacement of !4448 (closed), which was opened from a fork branch. Scope/changes are the same. Please continue review here.

Summary

This MR improves UTXO signing safety and RPC resilience, and aligns ZEC/BTC RPC client interfaces so one shared client abstraction can be used.

Problem

  • Vault-level locking did not consistently cover the full sign -> broadcast window, which can allow concurrent UTXO selection/broadcast races.
  • UTXO RPC wrapper calls did not consistently enforce context deadlines.
  • rpc.Client and zec.Client had mismatched interfaces, forcing split fields and chain-specific branching.
  • Simulation code still used the old rpc.NewClient signature.
  • UTXO fee state (lastFeeRate, minRelayFeeSats) was shared across scanner/consolidation paths without synchronized access.
  • "already in block chain" broadcast handling did not mark signer cache as signed on that branch.

Changes

  • Hold vault lock through broadcast in UTXO consolidate flow and signer flow (via lock-capability interface) to eliminate local double-spend risk on concurrent work.
  • Add timeout-aware context handling to UTXO RPC wrapper calls (Call and batch paths).
  • Pass configured HTTP timeout into UTXO RPC client creation.
  • Add CallContext and BatchCallContext to zec.Client.
  • Introduce a shared rpcClient interface (Call, BatchCall, CallContext, BatchCallContext) and use a single client field for both standard RPC and ZEC RPC implementations.
  • Update simulation UTXO constructor call to match new RPC client signature.

Additional changes in commit a5dd99b5

  • Convert UTXO fee fields to atomics and update all access sites to Load/Store:
    • minRelayFeeSats
    • lastFeeRate
  • Refactor consolidate flow:
    • Extract per-vault helper consolidateVaultUTXOs(...)
    • Return wrapped errors from helper
    • Log once at caller with vault context
  • In consolidate amount building:
    • Use getUtxoToSpend(..., 0) as count-based probe
    • Sum via per-UTXO sats conversion (btcutil.NewAmount) to avoid float accumulation drift
  • In BroadcastTx, when RPC returns "already in block chain", mark signer cache as signed before returning success.
  • Add a short code comment documenting why sats-per-UTXO summation is used.

Impact

  • Safer concurrent signing/broadcast behavior for UTXO vaults.
  • Better failure behavior on slow/stuck RPC calls via deadlines.
  • Less duplicated chain-conditional RPC code and cleaner client abstraction.
  • Removes unsynchronized shared fee-field access between goroutines.
  • Cleaner consolidate error flow (single log location with wrapped context).
  • Avoids potential rounding drift in consolidation total amount computation.
  • Ensures already-broadcast transactions are handled consistently by always recording them in the signer cache.

Test plan

  • make test passes
  • make lint passes
  • make test-simulation passes
Edited by ZlyDevMaya

Merge request reports

Loading
Loading