diff --git a/payjoin/src/input_type.rs b/payjoin/src/input_type.rs index bc8d11f9..dd1b4803 100644 --- a/payjoin/src/input_type.rs +++ b/payjoin/src/input_type.rs @@ -3,6 +3,7 @@ use std::fmt; use bitcoin::blockdata::script::{Instruction, Instructions, Script}; use bitcoin::blockdata::transaction::TxOut; use bitcoin::psbt::Input as PsbtInput; +use bitcoin::transaction::InputWeightPrediction; /// Takes the script out of script_sig assuming script_sig signs p2sh script fn unpack_p2sh(script_sig: &Script) -> Option<&Script> { @@ -92,6 +93,9 @@ impl InputType { .as_ref() .and_then(|script_buf| unpack_p2sh(script_buf.as_ref())) { + // nested segwit can only be detected if the input is signed, which it's not because + // final_script_sig gets cleared for sender inputs, and is unset at this stage for + // receiver inputs Some(script) if script.is_witness_program() => Self::segwit_from_script(script, true), Some(_) => Ok(InputType::P2Sh), @@ -129,17 +133,30 @@ impl InputType { } pub(crate) fn expected_input_weight(&self) -> bitcoin::Weight { + let iwp = self.input_weight_prediction(); + // Lengths of txid, index and sequence: (32, 4, 4). + // Multiply the lengths by 4 since the fields are all non-witness fields. + let weight_per_input = iwp.weight() + bitcoin::Weight::from_wu(4 * (32 + 4 + 4)); + weight_per_input + } + + fn input_weight_prediction(&self) -> InputWeightPrediction { use InputType::*; - bitcoin::Weight::from_non_witness_data_size(match self { + match self { P2Pk => unimplemented!(), - P2Pkh => 148, + P2Pkh => InputWeightPrediction::P2PKH_COMPRESSED_MAX, P2Sh => unimplemented!(), - SegWitV0 { ty: SegWitV0Type::Pubkey, nested: false } => 68, - SegWitV0 { ty: SegWitV0Type::Pubkey, nested: true } => 91, + SegWitV0 { ty: SegWitV0Type::Pubkey, nested: false } => + InputWeightPrediction::P2WPKH_MAX, + SegWitV0 { ty: SegWitV0Type::Pubkey, nested: true } => + // input script: 0x160014{20-byte-key-hash} = 23 bytes + // witness: = 72, 33 bytes + // https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki#p2wpkh-nested-in-bip16-p2sh + InputWeightPrediction::new(23, &[72, 33]), SegWitV0 { ty: SegWitV0Type::Script, nested: _ } => unimplemented!(), - Taproot => 58, - }) + Taproot => InputWeightPrediction::P2TR_KEY_NON_DEFAULT_SIGHASH, + } } }