Liana x Payjoin Integration — Dev Update Call Notes #699
Replies: 11 comments 13 replies
-
|
Thursday, May 15, 2025 Working POC Branch: We currently have a working version where two Liana wallets can send multiple Payjoin transactions back and forth. This proof-of-concept branch acts as a fast-paced sketching environment for experimental and breaking changes. The goal is to break off smaller, reviewable chunks and open pull requests against Liana’s Major blocker: This flow is hacky! we’re essentially re-processing the same state machine three different times, each time skipping certain states. What we really want is the ability to drive the state machine up to a certain point in one part of the application (where the wallet context and bitcoind rpc interface exists), then continue processing it elsewhere (where we have access to keys!). The session event log would make this much more manageable. There are still parts of the receiver state machine that need to be properly implemented, like skipping The 0.23 persister doesn’t allow us to persist metadata alongside the receiver in its initial state -- similar to the issue in the Boltz integration. Instead of trying to work around this, we are using the no-op persister and shifting to the session event log model as early as possible during development. Open question:
Action Items:
|
Beta Was this translation helpful? Give feedback.
-
Why is this ideal? I would assume GUI should handle presentation only and business logic should happen in the daemon.
A solution exists in bdk_wallet, of course, since it supports this. Can that code be used? |
Beta Was this translation helpful? Give feedback.
-
|
Wednesday, May 28 2025 Current StatusSEL is proving to be useful for saving and resuming the receiver state machine (see last update). Integration with the new Built an ergonomic interface for accessing and updating application-specific session metadata. However, some metadata like the BIP21 URI and original PSBT should instead be reconstructed from session history rather than redundantly stored. We’re still re-inserting BIP32 paths into the PSBT in Lianad. This step should be removed entirely, as we can now persist the session after contributing inputs and resume it in the GUI to call TODO
Current BlockerWe're stuck in the sender state machine when reading from the directory ( |
Beta Was this translation helpful? Give feedback.
-
|
Thur June 5 2025 What was done
Action Items
Open Questions
Blockers
|
Beta Was this translation helpful? Give feedback.
-
Artur's Update on Liana Integration (July 2nd)PDK:As of today the PDK master (commit c3f1ce2) does not support If a user contribute that kind of That also happens when starting the workflow as a Sender via Here is a simple diagram of important pipelines that end up calling There is an open PR that tries to fix that (for Receiver) but it seems that it is not a simple change as the PR touches an important part of the PDK core codebase. Add expected_weight field to InputPair #772 Even with that PR merged we will still need to change the Sender pipeline to allow Liana:Assuming PDK allows 1 - We need to get the weights of the given PSBT's inputs (as Sender and Receiver) so we need access to the 2 - Liana does signing on its GUI so we need to "stop" the PDK workflow, give the PSBT to the GUI so it can sign it and the "resume" the PDK sessioin using the signed PSBT. pub fn finalize_proposal(
mut self,
wallet_process_psbt: impl Fn(&Psbt) -> Result<Psbt, ImplementationError>,
min_fee_rate: Option<FeeRate>,
max_effective_fee_rate: Option<FeeRate>,
) -> Result<PayjoinProposal, ReplyableError> {
// Note(arturgontijo): PSBT with final fee
let mut psbt = self.apply_fee(min_fee_rate, max_effective_fee_rate)?.clone();
// Remove now-invalid sender signatures before applying the receiver signatures
for i in self.sender_input_indexes() {
log::trace!("Clearing sender input {i}");
psbt.inputs[i].final_script_sig = None;
psbt.inputs[i].final_script_witness = None;
psbt.inputs[i].tap_key_sig = None;
}
let psbt = wallet_process_psbt(&psbt).map_err(ReplyableError::Implementation)?;
let payjoin_proposal = self.prepare_psbt(psbt);
Ok(payjoin_proposal)
}As the code is now is not possible to "inject" an external (signed by Liana's GUI) PSBT to that function, even if we try something like: // Example
let signed_and_finalized_by_gui_psbt = liana_gui::finalize_psbt(&mut psbt, secp);
let proposal = proposal
.finalize_proposal(
|_| Ok(signed_and_finalized_by_gui_psbt.clone()),
None,
Some(FeeRate::from_sat_per_vb(5).unwrap()),
)
.save(persister)?;That code works as I'm using it in the current PoC but the issue is that we are not giving the "PSBT with fee" to Liana's GUI here, we are using a previous version of that PSBT (without proper fee calculation) and then forcing PDK to use it, ignoring the right PSBT. I've tried to use this current logic (using I'd recommend split this workflow into 2, so users can extract the PSBT with fees, sign/finalize it and send it back to PDK. 3 - At A workaround would be using something like: for index in 0..spend_psbt.inputs.len() {
match spend_psbt.finalize_inp_mut(&self.secp, index) {
Ok(_) => log::info!("Finalizing input at: {}", index),
Err(e) => log::warn!("Not finalizing input at: {} | {}", index, e),
}
}4 - Throwing /// Get some information about a PSBT input spending Liana coins.
/// This analysis assumes that:
/// - The PSBT input actually spend a Liana coin for this descriptor. Otherwise the analysis will be off.
/// - The signatures contained in the PSBT input are valid for this script.
pub fn partial_spend_info_txin( ... )That method does not allow not owned "coins" (external inputs). |
Beta Was this translation helpful? Give feedback.
-
|
Brain dump of current Liana integration progress. This is a non-exaustive list of what has been done what needs to be done. Anything that is actionable should get ticketed here. High-Level Codebase Changes and Remaining WorkPDK
Foreign Input Support
GUISend Panel
Receive Panel
Transaction Page
PSBT Page
Bitcoind
Lianad
Database
Error HandlingThe current impl does not introduce novel error types. Instead it uses Box which doesn't seem like a standard used anywhere else in the Liana codebase. Misc. notesThe current priority is to get Liana to payjoin-cli smoke tests working without any workaround or hacks introduced into pdk or liana. The Liana sender to pdk-cli recv flow is working after applying some fixes however the liana recv seems to have a contraint. Mainly that we cannot finalize the psbt in the GUI due to one major limitation: we dont have access to the DB and the session persister. Currently lianad picks up on the fact that the recv has signed the og psbt and injects the finalized psbt BUT the psbt that was signed did not apply the correct recv fees. So the sender will complain and close their side of the session. As of writing this I don't have a great solution but I will follow up when I do. |
Beta Was this translation helpful? Give feedback.
-
|
A note on my end the environment to start liana-gui on my machine has been particularly arduous. I finally created a very basic Ubuntu VM to have an OS that could finally get it up and running and have begun implementing the unimplemented receiver state checks. |
Beta Was this translation helpful? Give feedback.
-
In attempting to get these receiver state checks implemented we have found that because liana has direct access to these closures and is not working through an ffi layer like other integrations. As a result we need to find a different path for implementing these closures in liana. The issue is arising because the database calls in liana all use We are presented with a few options going forward
At the moment I think that we can avoid changing anything in rust-payjoin as liana does make some fields accesible from within the db that allows us to do these checks within the wallet. Long term, however, it would be good to at least make a decision on how much we should limit these closures whether we feel giving wallets the ability to work with some mutability or not by changing the rust-payjoin functions to accept something more permissive with |
Beta Was this translation helpful? Give feedback.
-
|
Some bugs/ bad ux I found in the payjoin-flow GUI
lianad
|
Beta Was this translation helpful? Give feedback.
-
|
This week:
Error handling:
|
Beta Was this translation helpful? Give feedback.
-
|
Attendees: Manuel Gatti (liana), Armin (PDK), Ben Allen (PDK), Yashraj (Bitcoin Design Community)
|
Beta Was this translation helpful? Give feedback.

Uh oh!
There was an error while loading. Please reload this page.
-
This discussion consists of notes taken during the Liana Payjoin integration dev update calls.
Beta Was this translation helpful? Give feedback.
All reactions