You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Uniformly use primitive types in FFI boundary, with runtime validation #738
On one hand strong types make it harder to misue the API.
on the other hand, they require conversion on the implementers side. It could get even trickier if there are different versions of bdk-ffi and payjoin-ffi that want to work together but use different bitcoin-ffi versions.
Perhaps to compose these, we need a bdk-ffi that depends on payjoin-ffi with a feature gate so that the same bitcoin-ffi dependency can be used without duplication. @thunderbiscuit Have you given this any thought before?
Earlier, I raised a concern about some of the BTC types generating here. I performed a smoke test, and the Bitcoin types work just fine here...
Here are my thoughts on the issue: It may be possible to maintain the public FFI surface for simple primitives (PSBT strings, Satoshi u64, plain URLs) in the 1.0 cycle and compensate with stricter runtime validation. That avoids binding ourselves to a specific Bitcoin-FFI release that we don’t control and keeps BDK-FFI integrators from juggling multiple wrapper hierarchies.
If we want to help adopters use strong types, expose them via optional helpers: e.g., add a small compat module that accepts/returns bitcoin_ffi::Address/Amount behind a feature flag. This keeps the core API stable while giving teams who manage their dependency graph tightly the choice to opt in. Which looks something like this:
The default API stays on plain strings/u64, so anyone who ignores the helper feature can treat bitcoin-ffi as an internal implementation detail and avoid synchronizing versions. Only users who opt in to the helper module (and therefore choose to work with bitcoin_ffi::Address, Amount, etc.) would take on the dependency-alignment responsibility; it becomes a conscious trade-off rather than a requirement for everyone.
I'd say I'm biased towards a stricter, but I'm making the assumption that library versions won't be in sync much of the time
It may be possible to maintain the public FFI surface for simple primitives (PSBT strings, Satoshi u64, plain URLs) in the 1.0 cycle and compensate with stricter runtime validation. That avoids binding ourselves to a specific Bitcoin-FFI release that we don’t control and keeps BDK-FFI integrators from juggling multiple wrapper hierarchies.
I generally agree with this. I think our current approach is basically a mix of both, which is the worst of both worlds. Given the interop requirements with bdk-ffi it seems cleaner to use primitives for all boundary crossings, with runtime validation.
We can keep exporting bitcoin_ffi alongside payjoin_ffi as a convenience for implementers (for example converting callback inputs for processing), but remove the bitcoin_ffi types from the API.
sounds good to me. I hadn't considered the bitcoin-ffi release cadence. Crossing boundaries with primitives and validating at runtime sounds appropriate for the usecases in our medium-term roadmap. Perhaps bitcoin-ffi will. get up a more predictable release cadence sometime in the future at which point we can reconsider.
changed the title [-]Consider using bitcoin_ffi types like Address and Amount rather than String / u64[/-][+]Uniformly use primitive types in FFI boundary, with runtime validation[/+]on Oct 8, 2025
Activity
spacebear21 commentedon Sep 18, 2025
Adding to 1.0 milestone not necessarily because I think we should use strong types, but we should make a decision for 1.0 either way.
arminsabouri commentedon Sep 29, 2025
Re-assigning this to @chavic
chavic commentedon Oct 1, 2025
Earlier, I raised a concern about some of the BTC types generating here. I performed a smoke test, and the Bitcoin types work just fine here...
Here are my thoughts on the issue: It may be possible to maintain the public FFI surface for simple primitives (PSBT strings, Satoshi u64, plain URLs) in the 1.0 cycle and compensate with stricter runtime validation. That avoids binding ourselves to a specific Bitcoin-FFI release that we don’t control and keeps BDK-FFI integrators from juggling multiple wrapper hierarchies.
If we want to help adopters use strong types, expose them via optional helpers: e.g., add a small compat module that accepts/returns bitcoin_ffi::Address/Amount behind a feature flag. This keeps the core API stable while giving teams who manage their dependency graph tightly the choice to opt in. Which looks something like this:
As opposed to:
The default API stays on plain strings/u64, so anyone who ignores the helper feature can treat bitcoin-ffi as an internal implementation detail and avoid synchronizing versions. Only users who opt in to the helper module (and therefore choose to work with bitcoin_ffi::Address, Amount, etc.) would take on the dependency-alignment responsibility; it becomes a conscious trade-off rather than a requirement for everyone.
I'd say I'm biased towards a stricter, but I'm making the assumption that library versions won't be in sync much of the time
spacebear21 commentedon Oct 2, 2025
I generally agree with this. I think our current approach is basically a mix of both, which is the worst of both worlds. Given the interop requirements with bdk-ffi it seems cleaner to use primitives for all boundary crossings, with runtime validation.
We can keep exporting bitcoin_ffi alongside payjoin_ffi as a convenience for implementers (for example converting callback inputs for processing), but remove the bitcoin_ffi types from the API.
@DanGould / @nothingmuch any objections?
DanGould commentedon Oct 2, 2025
sounds good to me. I hadn't considered the bitcoin-ffi release cadence. Crossing boundaries with primitives and validating at runtime sounds appropriate for the usecases in our medium-term roadmap. Perhaps bitcoin-ffi will. get up a more predictable release cadence sometime in the future at which point we can reconsider.
[-]Consider using bitcoin_ffi types like Address and Amount rather than String / u64[/-][+]Uniformly use primitive types in FFI boundary, with runtime validation[/+]chavic commentedon Dec 10, 2025
This PR #1191 should take care of this issue