fix(ethereum): route GetWallet's wallet-ID fallback by scheme, not error type#4122
Merged
mswilkison merged 1 commit intoJun 27, 2026
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…ror type
GetWallet derived a legacy wallet ID on ANY error from the canonical walletID
accessor. For a FROST wallet on a canonical Bridge, a transient call failure
would silently yield the left-padded legacy ID, and callers use
WalletChainData.WalletID to choose P2TR (FROST) vs P2WPKH (legacy) scripts, so it
would build or search the wrong wallet script.
The error type cannot reliably tell a legacy on-chain Bridge -- where the walletID
eth_call returns a normal RPC/ABI error even with the current binding -- from a
transient failure, so distinguishing by error is fragile and breaks legacy
deployments (Codex P1 on the first revision of this PR). Route the fallback by
SCHEME instead, using the wallet's ECDSA wallet ID (zero => FROST, non-zero =>
legacy ECDSA), which GetWallet already has:
- Legacy ECDSA wallet: its canonical wallet ID equals the legacy derivation, so
fall back on any accessor error (and it is the only option on a legacy Bridge
lacking the accessor).
- FROST wallet: requires the canonical ID; surface the error rather than return
a wrong legacy ID. A FROST wallet only exists on a canonical-ID Bridge, so the
error is genuinely transient.
Extracted into resolveWalletID with TestResolveWalletID covering all four cases.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
3e0e61c to
e3eef0b
Compare
71ce32b
into
feat/frost-schnorr-migration-scaffold
16 checks passed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Addresses a Codex finding (relayed via the #4119 review):
TbtcChain.GetWalletderived a legacy wallet ID on any error from the canonicalwalletIDaccessor. For a FROST wallet on a canonical Bridge, a transient call failure would silently yield the left-padded legacy ID — and callers useWalletChainData.WalletIDto choose P2TR (FROST) vs P2WPKH (legacy) scripts, so the node would build or search the wrong wallet script.Why route by scheme (revised after Codex P1)
The first revision distinguished by error type (a sentinel for the missing accessor, surface everything else). Codex correctly flagged a P1 regression: a legacy on-chain Bridge built with the current generated binding still satisfies the accessor interface, so its missing
walletIDfunction returns a normal RPC/ABI error — not the sentinel — and that revision would surface it and breakGetWalleton exactly the legacy deployments the fallback exists for. Error type cannot reliably separate "function absent on-chain" from "transient."So this routes by scheme, using the wallet's
EcdsaWalletID(whichGetWalletalready reads, and which the codebase already uses to infer scheme — zero ⇒ FROST):EcdsaWalletID != 0): its canonical wallet ID equals its legacy derivation, so fall back on any accessor error — and it's the only option on a legacy Bridge lacking the accessor.EcdsaWalletID == 0): requires the canonical ID; surface the error rather than return a wrong legacy ID. A FROST wallet only exists on a canonical-ID Bridge, so such an error is genuinely transient.Logic is extracted into
resolveWalletID(bridge, walletPublicKeyHash, ecdsaWalletID).Tests
TestResolveWalletIDcovers all four cases: accessor success → canonical; FROST + accessor error → surfaced; legacy + accessor error → legacy fallback (the P1 regression guard — verified to fail if the routing surfaces errors for legacy wallets); legacy + missing-accessor binding → legacy fallback. gofmt +go vetclean; fullpkg/chain/ethereumsuite passes.Found during the Codex review batch on #4115–#4120; revised per the Codex P1 re-review.
Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com
🤖 Generated with Claude Code