Skip to content

Insulate bitcoin uri - #1756

Merged
DanGould merged 2 commits into
payjoin:masterfrom
spacebear21:insulate-bitcoin-uri
Jul 23, 2026
Merged

Insulate bitcoin uri#1756
DanGould merged 2 commits into
payjoin:masterfrom
spacebear21:insulate-bitcoin-uri

Conversation

@spacebear21

Copy link
Copy Markdown
Collaborator

Follow up to #1702 for the bitcoin-uri crate.

Co-authored-by: Claude Opus 4.8

Pull Request Checklist

Please confirm the following before requesting review:

@spacebear21
spacebear21 force-pushed the insulate-bitcoin-uri branch from 972f06d to 56b3d26 Compare July 22, 2026 02:14
@coveralls

coveralls commented Jul 22, 2026

Copy link
Copy Markdown
Collaborator

Coverage Report for CI Build 29973580452

Coverage increased (+0.1%) to 86.49%

Details

  • Coverage increased (+0.1%) from the base build.
  • Patch coverage: 6 uncovered changes across 4 files (144 of 150 lines covered, 96.0%).
  • 1 coverage regression across 1 file.

Uncovered Changes

File Changed Covered %
payjoin/src/core/uri/error.rs 21 19 90.48%
payjoin/src/core/uri/mod.rs 78 76 97.44%
payjoin-cli/src/app/v1.rs 2 1 50.0%
payjoin-cli/src/app/v2/mod.rs 1 0 0.0%
Total (11 files) 150 144 96.0%

Coverage Regressions

1 previously-covered line in 1 file lost coverage.

File Lines Losing Coverage Coverage
payjoin-cli/src/app/v2/mod.rs 1 57.73%

Coverage Stats

Coverage Status
Relevant Lines: 16196
Covered Lines: 14008
Line Coverage: 86.49%
Coverage Strength: 340.53 hits per line

💛 - Coveralls

@DanGould DanGould left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cACK with some comments

Comment thread payjoin-ffi/src/uri/error.rs Outdated
Comment thread payjoin/src/core/uri/error.rs Outdated
///
/// The foreign error is erased behind a boxed trait object so that it does
/// not appear in the public API, while preserving the `source()` chain.
Bip21(Box<dyn std::error::Error + Send + Sync>),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Bip21(Box<dyn std::error::Error + Send + Sync>),
Bip21(bitcoin_uri::de::UriError),

Because this is an internal variant in InternalUriParseError it doesn't need to be and shouldn't be boxed because boxing buys us nothing. Comment is not right.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're absolutely right! just kidding but yes, fixed.

pub(crate) fn from_err(err: impl std::fmt::Display) -> Self { Self { msg: err.to_string() } }
}
#[derive(Debug, thiserror::Error, uniffi::Object)]
#[uniffi::export(Debug, Display)]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any rationale for dropping Eq from this list?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, added the rationale to the commit message: Eq cannot be derived anymore because the Bip21 variant of payjoin::UriParseError holds a bitcoin_uri::de::UriError, which doesn't implement Eq.

/// parameters were invalid.
#[cfg(test)]
pub(crate) fn payjoin_params(&self) -> Option<&PjParseError> {
match &self.0 {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I spent some time considering making this pub bc it prevents some hacks happening down stream. But I don't recomend it

Suggested change
match &self.0 {
pub fn pj_parse_error(&self) -> Option<&PjParseError> {

Cove blind-retries today on any Uri::try_from failure it hand-strips pj/pjos and parses a second time (address.rs#L245) because one opaque error can't distinguish a bad address from bad pj params.

Rather than papering over here though, since they have something that ~works I think we're better just leaving what you have, a more minimal api, and doing a bitcoin_uri crate 0.2 overhaul sooner than later

@spacebear21
spacebear21 force-pushed the insulate-bitcoin-uri branch from 56b3d26 to 5b6eb8a Compare July 23, 2026 01:27
@spacebear21
spacebear21 marked this pull request as ready for review July 23, 2026 01:31
@spacebear21
spacebear21 requested a review from DanGould July 23, 2026 01:31
Part of the 1.0 API hardening: remove the foreign bitcoin_uri types
from payjoin's public API so that a breaking release of bitcoin_uri no
longer forces a breaking release of payjoin. This follows the same
approach as the bitcoin-ohttp and bitcoin-hpke insulation in payjoin#1702.

Previously `Uri` and `PjUri` were type aliases to `bitcoin_uri::Uri`,
so the wrapped type, its public fields (including `bitcoin_uri::Param`
labels and messages), the `bitcoin_uri::de::Error` parse error, and the
`bitcoin_uri::Uri` returned by `check_pj_supported` were all reachable
through the public API. The parser traits were also implemented directly
on the public `MaybePayjoinExtras` and `PayjoinExtras` types.

The crate now only names `bitcoin_uri` in private newtype fields and on
the private adapters. No `bitcoin_uri` type or trait impl is reachable
through the public API.
The FFI `PjParseError` flattened the parse error into a `String` because
`payjoin::Uri`'s parse error used to be the foreign
`bitcoin_uri::de::Error`, whose type could not be carried across the FFI
boundary.

Now that parsing returns payjoin's own `UriParseError`, which implements
`std::error::Error`, it can be wrapped directly with
`#[error(transparent)]` and `#[from]`. As a result it is also renamed to
`UriParseError` to match the core library naming convention.

`Eq` cannot be derived anymore because the `Bip21` variant of
`payjoin::UriParseError` holds a `bitcoin_uri::de::UriError`, which
doesn't implement `Eq`.
@spacebear21
spacebear21 force-pushed the insulate-bitcoin-uri branch from 5b6eb8a to 35a107c Compare July 23, 2026 02:07

@DanGould DanGould left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK 35a107c

@DanGould DanGould left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK 35a107c

@DanGould
DanGould merged commit 9e14083 into payjoin:master Jul 23, 2026
35 checks passed
@DanGould DanGould mentioned this pull request Jul 23, 2026
18 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants