fix!: return errors from wallet address methods - #1114
Arowolokehinde wants to merge 1 commit into
Conversation
Five `Wallet` methods reached upstream `expect` calls that panic instead of returning an error. `peek_address` panicked for derivation indexes in the BIP32 hardened range, and for descriptors with no address form. The same `must have address form` panic is reachable from `reveal_next_address`, `next_unused_address`, `reveal_addresses_to` and `list_unused_addresses`, so all five now return `Result<_, AddressError>`. The checks run before delegating to `bdk_wallet`, which panics rather than returning an error, so there is no `Err` to map. This also stops the three mutating methods from staging a derivation index change before failing. The `has_wildcard` guard preserves the upstream behaviour of clamping the index to 0 for non-wildcard descriptors. `list_unused_addresses` previously returned an empty list rather than panicking on a bare descriptor wallet, since nothing can be revealed on one. It now returns `BareDescriptorAddr`, for consistency with the other four methods. The signatures become fallible, a breaking change for Swift callers. Kotlin and Python remain source-compatible.
f7175c7 to
c9aa633
Compare
Ugarba202
left a comment
There was a problem hiding this comment.
This is an excellent catch and a very necessary fix! 💯 Mobile developers definitely prefer handling a thrown error over a complete app-crashing native panic.
I pulled the branch locally and ran through some checks:
- Test Suite Verification: Ran the standard
cargo testsuite, and all 77 unit tests passed. - New Test Coverage: The new tests you added (like
test_peek_address_bare_descriptor_returns_errorandtest_peek_address_above_max_index_returns_error) perfectly cover the new guard logic. - API Break Acknowledgment: Adding the
AddressErrorreturn type to all five address methods is absolutely the right call to maintain consistency, even if it forces atryblock in Swift. It's much better to have API-breaking safety than unpredictable panics.
The guards you placed before delegating tobdk_walletare clean and effective. Thanks for making the mobile bindings more robust!
|
ACK c9aa633. I checked the bounds handling, bare-descriptor guard, and the behavior of the other four address-returning methods against the upstream bdk_wallet implementation. The wildcard check in peek_address looks correct, especially preserving the existing behavior where non-wildcard descriptors ignore the supplied index. Guarding the address form before calling the mutating upstream methods also avoids staging derivation changes before returning the error. The Rust regression coverage looks good across the max index, out-of-range index, non-wildcard descriptors, and bare descriptors. Non-blocking: since the main goal here is turning native panics into binding-visible errors, it would be nice to have one Kotlin or Swift regression test that actually catches the generated AddressError, for example verifying the out-of-range index field. The existing Rust coverage already proves the wrapper behavior, so I wouldn't block this PR on it. Otherwise this looks good to me. |
Description
Fixes #1105
Wallet::peek_addressreached two upstreamexpectcalls in bdk_wallet that panic: derivationindexes in the BIP32 hardened range, and descriptors with no address form, i.e.
bare descriptors such as
pk(...)and top-levelmulti(...).Per the discussion on the issue, the same
must have address formpanic isreachable from
reveal_next_address,next_unused_address,reveal_addresses_toand
list_unused_addresses, so all five address methods now returnResult<_, AddressError>.The guard runs before delegating to
bdk_wallet, which panics rather thanreturning an error, so there is nothing to
map_err. It also means the threemutating methods no longer stage a derivation index change before failing.
Notes to the reviewers
AddressErroris shared across all five, though onlypeek_addresscan returnIndexOutOfBounds.list_unused_addressesis a behaviour change rather than a panic fix: itpreviously returned an empty list on a bare descriptor wallet, because nothing
can be revealed on one. It now returns an error, for consistency with the other
four.
Swift needs
tryat three call sites. Kotlin and Python are source-compatible.Changelog
changelog: breakingDocumentation
bdk_walletChecklists
All Submissions:
cargo fmtandcargo clippybefore committingchangelog:*labelBugfixes: