Repository navigation
Pay Houdini ZEC unified addresses to their t1 receiver - #512
Conversation
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
503c762 to
1621b78
Compare
peachbits
left a comment
There was a problem hiding this comment.
I checked the decoder against a separate ZIP-316 encoder written on Python's hashlib.blake2b (with person) and a hand-written bech32m and F4Jumble. It rebuilds all 60 vector strings from their receivers, and each vector's P2PKH receiver is the BIP-44 key m/44'/133'/account'/0/index of its root seed. Against getUnifiedTransparentAddress, 200 random P2PKH UAs, 50 P2SH UAs and 50 shielded-only UAs round-trip, as do an all-uppercase UA, unknown one- and three-byte typecodes, and a 17 KB item that runs the G block counter past 255. The utest, uregtest and tex HRPs, mixed case, a bech32 checksum, a flipped or dropped character, padding for another HRP, a 47-byte payload, a truncated item, a non-canonical size and 19- or 21-byte receivers all throw. The only gap I found is ZIP-316's item rules (inline 1).
In houdini.ts, only a t1 reaches addressTo, the saved action keeps the pasted address, and a t3, shielded-only or malformed address fails before any quote. Accepting t3, sending the pasted address to Houdini, saving the t1 on the action, letting decoder errors through, breaking F4Jumble, changing the P2SH prefix and throwing on unknown typecodes each fail a new test. Locally tsc and eslint are clean and both suites pass.
Non-blocking: inline 1 (ZIP-316's item rules) and inline 2 (tests for the checks after the checksum).
bb6a52e to
3929ce9
Compare
|
Both inlines are addressed in 24523b3: the ZIP-316 item rules (order, uniqueness, one transparent receiver) and tests for the checks after the checksum. tsc is clean and all 286 tests pass. |
Decodes a mainnet ZIP-316 unified address (bech32m, F4Jumble, item parse) and returns its transparent receiver as a t1 or t3 address. Tested against the official zcash-test-vectors set.
A pasted unified address now pays out to its transparent P2PKH receiver, since Houdini accepts t1 only. The saved swapSend action keeps the unified address the user entered. A unified address without a t1 receiver still gets the clear transparent-only error.
3929ce9 to
2aa7a98
Compare
CHANGELOG
Does this branch warrant an entry to the CHANGELOG?
Dependencies
EdgeApp/edge-exchange-plugins#510 (this branch is stacked on it)
Description
Asana task
HoudiniSwap accepts only transparent (t1) Zcash payout addresses. With #510 alone, a Swap & Send or Stealth Send to a pasted unified address (u1) gets the t1-only error, even when the u1 carries a transparent receiver. This branch pays such a u1 out to that receiver.
src/util/zcashUnifiedAddress.tsdecodes a mainnet ZIP-316 unified address in pure JS: bech32m without the 90-character limit, inverse F4Jumble (BLAKE2b with personalization), the HRP padding check, then the item list. It returns the transparent receiver as a t1 (P2PKH) or t3 (P2SH) address, orundefinedwhen the u1 has none. It throws on malformed input or a non-uprefix, which rejectsutest.houdini.tssends the decoded t1 to Houdini asaddressToon both the exchange and dex order bodies. A t1 passes through unchanged. A u1 without a t1 receiver (shielded-only or P2SH-only) and any other non-t1 address keep the clear error from Pay Houdini ZEC payouts to the t1 address #510.swapSendaction keeps the u1 the user entered aspayoutAddress.@noble/hashesis now a direct dependency. The lockfile already held 1.4.0 as a production transitive dependency, and nothing new is fetched.Tests:
undefined.On the iOS simulator, the agent account's own Zcash u1 was pasted as the recipient in the BTC Send scene. HoudiniSwap quoted, and the swap of 0.00035569 BTC reached the success scene. Houdini's order record for
bjoTdA9Kb45kPM8LZHxRZMhasreceiverAddresst1Pw5MC1ZFx79qZBf1f9VHgFe4bkz53AVoN, the t1 the decoder returns for that u1. The transaction's Exchange Details show the u1 as the payout address.Note
Medium Risk
Changes which on-chain address Houdini orders use for Zcash payouts; incorrect decoding could misroute funds, though coverage includes official ZIP-316 vectors and integration tests.
Overview
HoudiniSwap can now accept a pasted mainnet Zcash unified (
u1) address when it embeds a P2PKH transparent receiver, instead of failing before quote with a t1-only error or Houdini’s opaquemaxLength 200validation.A new
getUnifiedTransparentAddresshelper decodes ZIP-316 unified addresses (bech32m, F4Jumble inverse, receiver parsing) and returns the embedded t1 or t3 transparent address.getZcashOrderAddressin the Houdini plugin uses it soaddressToon exchange and dex orders is always an accepted t1, whilepayoutAddresson the saved swap action still records what the user entered. Shielded-only unified addresses, t3-only unified receivers, Sapling, and malformed inputs are still rejected up front with the clear t1-only message.Adds
@noble/hashesfor BLAKE2b/SHA256 in the decoder, plus ZIP-316 vector tests and expanded Houdini offline Zcash cases.Reviewed by Cursor Bugbot for commit bb6a52e. Bugbot is set up for automated code reviews on this repo. Configure here.
Test evidence
bb6a52ePay Houdini ZEC unified addresses to their t1
2026-10-17
🪓 Other swap providers disabled locally in corePlugins.ts so the Send scene quote comes from HoudiniSwap; reverted before commit
1. 🪓 houdini quote pasted u1
2. 🪓 swap success
3. 🪓 exchange details