rust-payjoin icon indicating copy to clipboard operation
rust-payjoin copied to clipboard

Input weight prediction for P2WSH inputs

Open arminsabouri opened this issue 8 months ago • 2 comments

We error out of we cannot predict the input weight of a p2wsh input here. Wallets that spend non-key spend policies such as Liana cannot intergrate. I don't have a great solution right now. I wouldn't be suprised in miniscript folks have encountered similar issues. Just wanted to make this issue before I forget.

Edit: tagging @spacebear21 . I think you have the most familiarity with this part of the code.

arminsabouri avatar Apr 17 '25 13:04 arminsabouri

This is half true, if you only have the script hash you can't estimate the weight, presumably if your wallet is making p2sh outputs it also knows the script which can be used to calculate that weight when spent.

Making an affordance for this scenario is the missing piece.

DanGould avatar Apr 17 '25 14:04 DanGould

I agree this should be solvable by manually calculating the redeem_script length for p2sh inputs, or the witness_script length for p2wsh inputs. The primary reason I didn't implement it is because it was previously not implemented either.

https://github.com/payjoin/rust-payjoin/issues/583 is a related issue that would ensure any p2wsh/p2sh InputPair is properly constructed with the relevant script details.

spacebear21 avatar Apr 17 '25 15:04 spacebear21

If we calculate the weight of just the witness script we would not be taking into account the weight of the witness stack elements that would satisfy that witness script. In general I am not sure rust-payjoin can (or should) try to estimate the worst case input satifiability weight for p2wsh or other variable weight input types (p2sh, p2tr script path spends). For these input types we should have the application provide the predicted weight for their inputs and that can be provided in the input constructor. In summary, instead of witness_script we should expect the application to provide predicted weight and use the application provided value in expected_input_weight.

cc @arturgontijo

arminsabouri avatar Jun 10 '25 16:06 arminsabouri

Brain dump: We can extend #772 to support weight predictions for the sender by just updating expected_input_weight. For the sender the inputs will always include witness. If they are using p2wsh, by the time they predict the expected input weight they should have already signed their inputs. When they recieve the proposal, the recv inputs should also include witness. I am thinking something like this could work:

 P2wsh => {
                if !self.txin.witness.is_empty(){
                    return Ok(Weight::from_witness_data_size(self.txin.witness.size() as u64));
                } else if let Some(witness) = &self.psbtin.final_script_witness {
                    if !witness.is_empty() {
                        return Ok(Weight::from_witness_data_size(witness.size() as u64));
                    }
                }
                Err(InputWeightError::NotSupported)
            },

arminsabouri avatar Jul 08 '25 16:07 arminsabouri