[Version-unspecific] fix(bifrost/eth,zec,ada): keep using stale asgard addresses when MAYANode cannot be read

Summary

When GetAsgardPubKeys failed, the ETH and ZEC clients threw away their cached asgard list. ZEC's isAsgardAddress then returned false for every address, so the scanner treated the block's txs as unrelated and moved past them. A short MAYANode outage (a restart or an upgrade) could lose inbounds for good. On both chains getBlockRequiredConfirmation returned the error, and GetConfirmationCount turned it into 0 confirmations, so the check failed open. This MR ports thornode!4594 (e91742a061), the part MAYA had not applied to ETH and ZEC. BTC and DASH get the same fix in !879. It changes only bifrost, so it is not version-gated.

Changes

  • New utxo.GetAsgardAddressesCached in shared/utxo. If the refresh fails, it returns the last known addresses together with the error. An empty refresh never replaces a non-empty cache. The cache is still an atomic.Pointer. After a failed refresh the helper remembers the failure for AsgardRefreshBackoff (2s) and returns the stale addresses with the error without querying MAYANode again. The helper and its tests are byte-identical to the BTC/DASH parity MR (!879), which carries the same change, so the two MRs merge cleanly.
  • ETH: getAsgardAddresses now uses the helper. Confirmation counting no longer returns early on an asgard error. It uses the last known list, or none, so a vault spend counts as inbound value and can only raise the number of confirmations required.
  • ZEC: uses the helper, and isAsgardAddress keeps matching against the stale list. FetchTxs returns ErrRetryableBlockScan whenever the asgard list can't be refreshed, even with a stale list cached, since that list can miss a new vault. It does this before any reorg or scan bookkeeping. Confirmation counting fails closed, as on ETH.
  • Cardano (MAYA-only; the same fix adapted, since THOR has no Cardano):
    • getAsgardAddresses uses the shared utxo.GetAsgardAddressesCached (still capped at MaxAsgardAddresses), so a MAYANode read error returns the last known vault addresses instead of dropping them.
    • FetchTxs fails the block for a retry whenever the asgard list can't be refreshed, even with a stale list cached, so a deposit to a vault that became active since the last refresh is not skipped.
    • isAsgardAddress keeps matching the stale list, so OnObservedTxIn still records vault spends as self txs. With no list at all it fails closed: the tx is tracked as a customer tx and UTXO selection skips unconfirmed UTXOs.
    • Cardano confirmation counting does not use the asgard list, so it is unchanged.
  • Not changed: EVM (ARB/AVAX) does no asgard lookups and has instant finality.

Tests

  • shared/utxo: covers a fresh hit, a refresh, an error with and without a stale cache, and an empty refresh.
  • ETH asgard_cache_test.go: the stale cache is kept on error, and the confirmation count is 2, not 0, while the asgard read fails.
  • ZEC asgard_cache_test.go: isAsgardAddress matches against the stale list, FetchTxs retries the block when there is no cache and scans it normally when a stale cache exists, and the confirmation count is greater than 0 when the asgard read fails.
  • Cardano client_test.go: the block is scanned against the stale list, the stale cache is kept on error, and OnObservedTxIn records a vault spend as a self tx while the asgard read fails. A block with no cache still fails for a retry.
  • The new ETH, ZEC and Cardano tests fail without the fix. go test -tags mocknet -p 2 passes on ethereum/..., zcash/..., cardano/... and shared/....

Review follow-up (round 4)

  • 30e109c7a: Cardano and ZEC FetchTxs fail the block on any asgard refresh error, also with a stale list cached, so a deposit to a vault that became active since the last refresh is retried instead of skipped. Stale matching in isAsgardAddress and confirmation counting is kept.
  • e2f335244: GetAsgardAddressesCached remembers a failed refresh for AsgardRefreshBackoff (2s) and returns the stale addresses with the error without querying MAYANode again, instead of one request per address check.
  • 1a986f934: ETH and ZEC tests check the value counted for confirmations while the asgard read fails (a deposit counts; a vault spend is excluded only with a stale list holding the vault).
Edited by Bitol Maya

Merge request reports

Loading
Loading