Repository navigation
feat: enable Safe recovery for ALGO - #10012
Conversation
8d5d10d to
b851c51
Compare
|
|
b851c51 to
8e69c33
Compare
There was a problem hiding this comment.
the lazy signer is the right call. externalBackupSignature from #9984 can't work for the Safe flow, because the sig has to cover bytesToSign() and that depends on the balance and firstRound, which recover() fetches from the node. the mapper runs offline before any of that exists. can you add that to the description? right now it reads like scope creep, since WCN-2898 doesn't mention touching recover().
my main concern is that this leaves two hooks that do the same job. a pre-made signature is just a signer that ignores its input. and hbar and xlm will hit the same wall:
- hbar signs
bodyBytes, which depend on the balance and onstartTime(defaults to now at build time) - xlm signs
tx.hash(), which depends on the horizon sequence, balance, reserve and base fee
so externalBackupSignature has no real caller on the safe path in any coin, and we'd end up with three copies of this validate/sign/inject block.
suggestion, keeping it scoped to this PR:
- move the signer type into
sdk-corenext toExternalEd25519Signature, with a sharedassertValidExternalEd25519Signerand a small helper that callssign()and checks for 64 bytes. replacesSafeBackupExternalSignerinsafe/recovery.ts. - use that in algo, and drop
externalBackupSignaturefrom algo (clean cutover instead of two hooks). - leave hbar/xlm on the old hook for now. their tickets can cut over with ~15 lines each.
the shared validator also fixes the pub check in algo: Buffer.from(pub, 'hex').length === 32 accepts 'f1'.repeat(32) + 'zz' because node stops at the first bad char. the existing assertValidExternalEd25519Signature already uses a strict regex, so reuse that.
94b84b8 to
a57bae5
Compare
a57bae5 to
6442d7e
Compare
Makes sense - addressed and made a ticket to migrate the 2 coins: https://linear.app/bitgo/issue/WCN-3754 |
Add the missing mapper arm so Safe ALGO wallets recover end-to-end: - sdk-lib-safes: add `algoMultisigAddress` to compute the 2-of-3 Algorand multisig address from raw child pubs. - sdk-core: add the `ed25519Multisig` arm to `buildSafeRecoverKeyParams` producing ALGO-encoded keys + `rootAddress` and, for signed mode, a lazy `externalBackupSigner` closure over the seedless backup child's (kL, kR). The request type is now a discriminated union on `slot`. - sdk-core: move the lazy-signer shape to `ExternalEd25519Signer`,living next to `ExternalEd25519Signature`, with a shared `assertValidExternalEd25519Signer` and `signWithExternalEd25519Signer` helper that fails fast unless the signature is the required 64 bytes & verifies against the advertised public key. - sdk-coin-algo: `Algo.recover()` takes only `externalBackupSigner` (the pre-made `externalBackupSignature` hook is gone), signs the tx bytes lazily, and appends the backup signature; the seed path is unchanged Why `recover()` changes: the backup child is a soft BIP32-Ed25519 key with no seed, and its signature must cover `tx.bytesToSign()`, which depends on the on-chain balance and `firstRound` — both fetched from the node inside `recover()`. The `buildSafeRecoverKeyParams` mapper runs fully offline, before any of that exists, so a pre-made signature cannot be produced at map time. Hence the lazy signer: the mapper hands `recover()` a closure over the private extended-key halves, and `recover()` invokes it once the transaction is built. XLM and HBAR hit the same wall (their signatures cover Horizon sequence/balance/reserve/fee and bodyBytes/startTime respectively); they still use the pre-made-signature hook and will cut over to `ExternalEd25519Signer` in their own tickets. Ticket: WCN-2898
6442d7e to
7a24ab7
Compare
There was a problem hiding this comment.
Claude Code Review
This repository is configured for manual code reviews. Comment @claude review for a one-time review, or @claude review always to subscribe this PR to a review on every future push.
Tip: disable this comment in your organization's Code Review settings.
|
@claude were all of the comments resolved? |
|
Claude encountered an error —— View job I'll analyze this and get back to you. |
1 similar comment
|
Claude encountered an error —— View job I'll analyze this and get back to you. |
What
Add the missing mapper arm so Safe ALGO wallets recover end-to-end:
algoMultisigAddressto compute the 2-of-3 Algorand multisig address from raw child pubs.ed25519Multisigarm tobuildSafeRecoverKeyParams, producing ALGO-encoded keys +rootAddressand, for signed mode, a lazyexternalBackupSignerclosure over the seedless backup child's (kL, kR). The request type is now a discriminated union onslot.ExternalEd25519Signer, living next toExternalEd25519Signature, with a sharedassertValidExternalEd25519Signerand asignWithExternalEd25519Signerhelper that fails fast unless the signature is the required 64 bytes.Algo.recover()takes onlyexternalBackupSigner(the pre-madeexternalBackupSignaturehook is gone), signs the tx bytes lazily, and appends the backup signature; the seed path is unchanged.Why
recover()changesThe backup child is a soft BIP32-Ed25519 key with no seed, and its signature must cover
tx.bytesToSign(), which depends on the on-chain balance andfirstRound— both fetched from the node insiderecover(). The keycard →buildSafeRecoverKeyParamsmapper runs fully offline, before any of that exists, so a pre-made signature cannot be produced at map time. Hence the lazy signer: the mapper handsrecover()a closure over the private extended-key halves, andrecover()invokes it once the transaction is built.XLM and HBAR hit the same wall (their signatures cover Horizon sequence/balance/reserve/fee and
bodyBytes/startTimerespectively); they still use the pre-made-signature hook and will cut over toExternalEd25519Signerin their own tickets.Ticket: WCN-2898