@@ -16,6 +16,7 @@ use bitcoin::blockdata::transaction::{Transaction, TxOut, TxIn, EcdsaSighashType
1616use bitcoin:: blockdata:: script:: { Script , Builder } ;
1717use bitcoin:: blockdata:: opcodes;
1818use bitcoin:: network:: constants:: Network ;
19+ use bitcoin:: psbt:: PartiallySignedTransaction ;
1920use bitcoin:: util:: bip32:: { ExtendedPrivKey , ExtendedPubKey , ChildNumber } ;
2021use bitcoin:: util:: sighash;
2122
@@ -218,6 +219,126 @@ impl_writeable_tlv_based_enum!(SpendableOutputDescriptor,
218219 ( 2 , StaticPaymentOutput ) ,
219220) ;
220221
222+ impl SpendableOutputDescriptor {
223+ /// Turns this into a [`bitcoin::psbt::Input`] which can be used to create a
224+ /// [`PartiallySignedTransaction`] which spends the given descriptor.
225+ ///
226+ /// Note that this does not include any signatures, just the information required to
227+ /// construct the transaction and sign it.
228+ pub fn to_psbt_input ( & self ) -> bitcoin:: psbt:: Input {
229+ match self {
230+ SpendableOutputDescriptor :: StaticOutput { output, .. } => {
231+ // Is a standard P2WPKH, no need for witness script
232+ bitcoin:: psbt:: Input {
233+ witness_utxo : Some ( output. clone ( ) ) ,
234+ ..Default :: default ( )
235+ }
236+ } ,
237+ SpendableOutputDescriptor :: DelayedPaymentOutput ( descriptor) => {
238+ // TODO we could add the witness script as well
239+ bitcoin:: psbt:: Input {
240+ witness_utxo : Some ( descriptor. output . clone ( ) ) ,
241+ ..Default :: default ( )
242+ }
243+ } ,
244+ SpendableOutputDescriptor :: StaticPaymentOutput ( descriptor) => {
245+ // TODO we could add the witness script as well
246+ bitcoin:: psbt:: Input {
247+ witness_utxo : Some ( descriptor. output . clone ( ) ) ,
248+ ..Default :: default ( )
249+ }
250+ } ,
251+ }
252+ }
253+
254+ /// Creates an unsigned [`PartiallySignedTransaction`] which spends the given descriptors to
255+ /// the given outputs, plus an output to the given change destination (if sufficient
256+ /// change value remains). The PSBT will have a feerate, at least, of the given value.
257+ ///
258+ /// The `locktime` argument is used to set the transaction's locktime. If `None`, the
259+ /// transaction will have a locktime of 0. It it recommended to set this to the current block
260+ /// height to avoid fee sniping, unless you have some specific reason to use a different
261+ /// locktime.
262+ ///
263+ /// Returns the PSBT and expected max transaction weight.
264+ ///
265+ /// Returns `Err(())` if the output value is greater than the input value minus required fee,
266+ /// if a descriptor was duplicated, or if an output descriptor `script_pubkey`
267+ /// does not match the one we can spend.
268+ ///
269+ /// We do not enforce that outputs meet the dust limit or that any output scripts are standard.
270+ pub fn create_spendable_outputs_psbt ( descriptors : & [ & SpendableOutputDescriptor ] , outputs : Vec < TxOut > , change_destination_script : Script , feerate_sat_per_1000_weight : u32 , locktime : Option < PackedLockTime > ) -> Result < ( PartiallySignedTransaction , usize ) , ( ) > {
271+ let mut input = Vec :: with_capacity ( descriptors. len ( ) ) ;
272+ let mut input_value = 0 ;
273+ let mut witness_weight = 0 ;
274+ let mut output_set = HashSet :: with_capacity ( descriptors. len ( ) ) ;
275+ for outp in descriptors {
276+ match outp {
277+ SpendableOutputDescriptor :: StaticPaymentOutput ( descriptor) => {
278+ if !output_set. insert ( descriptor. outpoint ) { return Err ( ( ) ) ; }
279+ input. push ( TxIn {
280+ previous_output : descriptor. outpoint . into_bitcoin_outpoint ( ) ,
281+ script_sig : Script :: new ( ) ,
282+ sequence : Sequence :: ZERO ,
283+ witness : Witness :: new ( ) ,
284+ } ) ;
285+ witness_weight += StaticPaymentOutputDescriptor :: MAX_WITNESS_LENGTH ;
286+ #[ cfg( feature = "grind_signatures" ) ]
287+ { witness_weight -= 1 ; } // Guarantees a low R signature
288+ input_value += descriptor. output . value ;
289+ } ,
290+ SpendableOutputDescriptor :: DelayedPaymentOutput ( descriptor) => {
291+ if !output_set. insert ( descriptor. outpoint ) { return Err ( ( ) ) ; }
292+ input. push ( TxIn {
293+ previous_output : descriptor. outpoint . into_bitcoin_outpoint ( ) ,
294+ script_sig : Script :: new ( ) ,
295+ sequence : Sequence ( descriptor. to_self_delay as u32 ) ,
296+ witness : Witness :: new ( ) ,
297+ } ) ;
298+ witness_weight += DelayedPaymentOutputDescriptor :: MAX_WITNESS_LENGTH ;
299+ #[ cfg( feature = "grind_signatures" ) ]
300+ { witness_weight -= 1 ; } // Guarantees a low R signature
301+ input_value += descriptor. output . value ;
302+ } ,
303+ SpendableOutputDescriptor :: StaticOutput { ref outpoint, ref output } => {
304+ if !output_set. insert ( * outpoint) { return Err ( ( ) ) ; }
305+ input. push ( TxIn {
306+ previous_output : outpoint. into_bitcoin_outpoint ( ) ,
307+ script_sig : Script :: new ( ) ,
308+ sequence : Sequence :: ZERO ,
309+ witness : Witness :: new ( ) ,
310+ } ) ;
311+ witness_weight += 1 + 73 + 34 ;
312+ #[ cfg( feature = "grind_signatures" ) ]
313+ { witness_weight -= 1 ; } // Guarantees a low R signature
314+ input_value += output. value ;
315+ }
316+ }
317+ if input_value > MAX_VALUE_MSAT / 1000 { return Err ( ( ) ) ; }
318+ }
319+ let mut tx = Transaction {
320+ version : 2 ,
321+ lock_time : locktime. unwrap_or ( PackedLockTime :: ZERO ) ,
322+ input,
323+ output : outputs,
324+ } ;
325+ let expected_max_weight =
326+ transaction_utils:: maybe_add_change_output ( & mut tx, input_value, witness_weight, feerate_sat_per_1000_weight, change_destination_script) ?;
327+
328+ let psbt_inputs = descriptors. iter ( ) . map ( |d| d. to_psbt_input ( ) ) . collect :: < Vec < _ > > ( ) ;
329+ let psbt = PartiallySignedTransaction {
330+ inputs : psbt_inputs,
331+ outputs : vec ! [ Default :: default ( ) ; tx. output. len( ) ] ,
332+ unsigned_tx : tx,
333+ xpub : Default :: default ( ) ,
334+ version : 0 ,
335+ proprietary : Default :: default ( ) ,
336+ unknown : Default :: default ( ) ,
337+ } ;
338+ Ok ( ( psbt, expected_max_weight) )
339+ }
340+ }
341+
221342/// A trait to handle Lightning channel key material without concretizing the channel type or
222343/// the signature mechanism.
223344pub trait ChannelSigner {
@@ -1171,97 +1292,40 @@ impl KeysManager {
11711292 )
11721293 }
11731294
1174- /// Creates a [`Transaction `] which spends the given descriptors to the given outputs, plus an
1175- /// output to the given change destination (if sufficient change value remains). The
1176- /// transaction will have a feerate, at least, of the given value .
1295+ /// Signs the given [`PartiallySignedTransaction `] which spends the given [`SpendableOutputDescriptor`]s.
1296+ /// The resulting inputs will be finalized and the PSBT will be ready for broadcast if there
1297+ /// are no other inputs that need signing .
11771298 ///
1178- /// Returns `Err(())` if the output value is greater than the input value minus required fee,
1179- /// if a descriptor was duplicated, or if an output descriptor `script_pubkey`
1180- /// does not match the one we can spend.
1181- ///
1182- /// We do not enforce that outputs meet the dust limit or that any output scripts are standard.
1299+ /// Returns `Err(())` if the PSBT is missing a descriptor or if we fail to sign.
11831300 ///
11841301 /// May panic if the [`SpendableOutputDescriptor`]s were not generated by channels which used
11851302 /// this [`KeysManager`] or one of the [`InMemorySigner`] created by this [`KeysManager`].
1186- pub fn spend_spendable_outputs < C : Signing > ( & self , descriptors : & [ & SpendableOutputDescriptor ] , outputs : Vec < TxOut > , change_destination_script : Script , feerate_sat_per_1000_weight : u32 , secp_ctx : & Secp256k1 < C > ) -> Result < Transaction , ( ) > {
1187- let mut input = Vec :: new ( ) ;
1188- let mut input_value = 0 ;
1189- let mut witness_weight = 0 ;
1190- let mut output_set = HashSet :: with_capacity ( descriptors. len ( ) ) ;
1191- for outp in descriptors {
1192- match outp {
1193- SpendableOutputDescriptor :: StaticPaymentOutput ( descriptor) => {
1194- input. push ( TxIn {
1195- previous_output : descriptor. outpoint . into_bitcoin_outpoint ( ) ,
1196- script_sig : Script :: new ( ) ,
1197- sequence : Sequence :: ZERO ,
1198- witness : Witness :: new ( ) ,
1199- } ) ;
1200- witness_weight += StaticPaymentOutputDescriptor :: MAX_WITNESS_LENGTH ;
1201- #[ cfg( feature = "grind_signatures" ) ]
1202- { witness_weight -= 1 ; } // Guarantees a low R signature
1203- input_value += descriptor. output . value ;
1204- if !output_set. insert ( descriptor. outpoint ) { return Err ( ( ) ) ; }
1205- } ,
1206- SpendableOutputDescriptor :: DelayedPaymentOutput ( descriptor) => {
1207- input. push ( TxIn {
1208- previous_output : descriptor. outpoint . into_bitcoin_outpoint ( ) ,
1209- script_sig : Script :: new ( ) ,
1210- sequence : Sequence ( descriptor. to_self_delay as u32 ) ,
1211- witness : Witness :: new ( ) ,
1212- } ) ;
1213- witness_weight += DelayedPaymentOutputDescriptor :: MAX_WITNESS_LENGTH ;
1214- #[ cfg( feature = "grind_signatures" ) ]
1215- { witness_weight -= 1 ; } // Guarantees a low R signature
1216- input_value += descriptor. output . value ;
1217- if !output_set. insert ( descriptor. outpoint ) { return Err ( ( ) ) ; }
1218- } ,
1219- SpendableOutputDescriptor :: StaticOutput { ref outpoint, ref output } => {
1220- input. push ( TxIn {
1221- previous_output : outpoint. into_bitcoin_outpoint ( ) ,
1222- script_sig : Script :: new ( ) ,
1223- sequence : Sequence :: ZERO ,
1224- witness : Witness :: new ( ) ,
1225- } ) ;
1226- witness_weight += 1 + 73 + 34 ;
1227- #[ cfg( feature = "grind_signatures" ) ]
1228- { witness_weight -= 1 ; } // Guarantees a low R signature
1229- input_value += output. value ;
1230- if !output_set. insert ( * outpoint) { return Err ( ( ) ) ; }
1231- }
1232- }
1233- if input_value > MAX_VALUE_MSAT / 1000 { return Err ( ( ) ) ; }
1234- }
1235- let mut spend_tx = Transaction {
1236- version : 2 ,
1237- lock_time : PackedLockTime ( 0 ) ,
1238- input,
1239- output : outputs,
1240- } ;
1241- let expected_max_weight =
1242- transaction_utils:: maybe_add_change_output ( & mut spend_tx, input_value, witness_weight, feerate_sat_per_1000_weight, change_destination_script) ?;
1243-
1303+ pub fn sign_spendable_outputs_psbt < C : Signing > ( & self , descriptors : & [ & SpendableOutputDescriptor ] , psbt : & mut PartiallySignedTransaction , secp_ctx : & Secp256k1 < C > ) -> Result < ( ) , ( ) > {
12441304 let mut keys_cache: Option < ( InMemorySigner , [ u8 ; 32 ] ) > = None ;
1245- let mut input_idx = 0 ;
12461305 for outp in descriptors {
12471306 match outp {
12481307 SpendableOutputDescriptor :: StaticPaymentOutput ( descriptor) => {
1308+ let input_idx = psbt. unsigned_tx . input . iter ( ) . position ( |i| i. previous_output == descriptor. outpoint . into_bitcoin_outpoint ( ) ) . ok_or ( ( ) ) ?;
12491309 if keys_cache. is_none ( ) || keys_cache. as_ref ( ) . unwrap ( ) . 1 != descriptor. channel_keys_id {
12501310 keys_cache = Some ( (
12511311 self . derive_channel_keys ( descriptor. channel_value_satoshis , & descriptor. channel_keys_id ) ,
12521312 descriptor. channel_keys_id ) ) ;
12531313 }
1254- spend_tx. input [ input_idx] . witness = Witness :: from_vec ( keys_cache. as_ref ( ) . unwrap ( ) . 0 . sign_counterparty_payment_input ( & spend_tx, input_idx, & descriptor, & secp_ctx) ?) ;
1314+ let witness = Witness :: from_vec ( keys_cache. as_ref ( ) . unwrap ( ) . 0 . sign_counterparty_payment_input ( & psbt. unsigned_tx , input_idx, & descriptor, & secp_ctx) ?) ;
1315+ psbt. inputs [ input_idx] . final_script_witness = Some ( witness) ;
12551316 } ,
12561317 SpendableOutputDescriptor :: DelayedPaymentOutput ( descriptor) => {
1318+ let input_idx = psbt. unsigned_tx . input . iter ( ) . position ( |i| i. previous_output == descriptor. outpoint . into_bitcoin_outpoint ( ) ) . ok_or ( ( ) ) ?;
12571319 if keys_cache. is_none ( ) || keys_cache. as_ref ( ) . unwrap ( ) . 1 != descriptor. channel_keys_id {
12581320 keys_cache = Some ( (
12591321 self . derive_channel_keys ( descriptor. channel_value_satoshis , & descriptor. channel_keys_id ) ,
12601322 descriptor. channel_keys_id ) ) ;
12611323 }
1262- spend_tx. input [ input_idx] . witness = Witness :: from_vec ( keys_cache. as_ref ( ) . unwrap ( ) . 0 . sign_dynamic_p2wsh_input ( & spend_tx, input_idx, & descriptor, & secp_ctx) ?) ;
1324+ let witness = Witness :: from_vec ( keys_cache. as_ref ( ) . unwrap ( ) . 0 . sign_dynamic_p2wsh_input ( & psbt. unsigned_tx , input_idx, & descriptor, & secp_ctx) ?) ;
1325+ psbt. inputs [ input_idx] . final_script_witness = Some ( witness) ;
12631326 } ,
1264- SpendableOutputDescriptor :: StaticOutput { ref output, .. } => {
1327+ SpendableOutputDescriptor :: StaticOutput { ref outpoint, ref output } => {
1328+ let input_idx = psbt. unsigned_tx . input . iter ( ) . position ( |i| i. previous_output == outpoint. into_bitcoin_outpoint ( ) ) . ok_or ( ( ) ) ?;
12651329 let derivation_idx = if output. script_pubkey == self . destination_script {
12661330 1
12671331 } else {
@@ -1288,17 +1352,42 @@ impl KeysManager {
12881352
12891353 if payment_script != output. script_pubkey { return Err ( ( ) ) ; } ;
12901354
1291- let sighash = hash_to_message ! ( & sighash:: SighashCache :: new( & spend_tx ) . segwit_signature_hash( input_idx, & witness_script, output. value, EcdsaSighashType :: All ) . unwrap( ) [ ..] ) ;
1355+ let sighash = hash_to_message ! ( & sighash:: SighashCache :: new( & psbt . unsigned_tx ) . segwit_signature_hash( input_idx, & witness_script, output. value, EcdsaSighashType :: All ) . unwrap( ) [ ..] ) ;
12921356 let sig = sign_with_aux_rand ( secp_ctx, & sighash, & secret. private_key , & self ) ;
12931357 let mut sig_ser = sig. serialize_der ( ) . to_vec ( ) ;
12941358 sig_ser. push ( EcdsaSighashType :: All as u8 ) ;
1295- spend_tx . input [ input_idx ] . witness . push ( sig_ser ) ;
1296- spend_tx . input [ input_idx] . witness . push ( pubkey . inner . serialize ( ) . to_vec ( ) ) ;
1359+ let witness = Witness :: from_vec ( vec ! [ sig_ser , pubkey . inner . serialize ( ) . to_vec ( ) ] ) ;
1360+ psbt . inputs [ input_idx] . final_script_witness = Some ( witness ) ;
12971361 } ,
12981362 }
1299- input_idx += 1 ;
13001363 }
13011364
1365+ Ok ( ( ) )
1366+ }
1367+
1368+ /// Creates a [`Transaction`] which spends the given descriptors to the given outputs, plus an
1369+ /// output to the given change destination (if sufficient change value remains). The
1370+ /// transaction will have a feerate, at least, of the given value.
1371+ ///
1372+ /// The `locktime` argument is used to set the transaction's locktime. If `None`, the
1373+ /// transaction will have a locktime of 0. It it recommended to set this to the current block
1374+ /// height to avoid fee sniping, unless you have some specific reason to use a different
1375+ /// locktime.
1376+ ///
1377+ /// Returns `Err(())` if the output value is greater than the input value minus required fee,
1378+ /// if a descriptor was duplicated, or if an output descriptor `script_pubkey`
1379+ /// does not match the one we can spend.
1380+ ///
1381+ /// We do not enforce that outputs meet the dust limit or that any output scripts are standard.
1382+ ///
1383+ /// May panic if the [`SpendableOutputDescriptor`]s were not generated by channels which used
1384+ /// this [`KeysManager`] or one of the [`InMemorySigner`] created by this [`KeysManager`].
1385+ pub fn spend_spendable_outputs < C : Signing > ( & self , descriptors : & [ & SpendableOutputDescriptor ] , outputs : Vec < TxOut > , change_destination_script : Script , feerate_sat_per_1000_weight : u32 , locktime : Option < PackedLockTime > , secp_ctx : & Secp256k1 < C > ) -> Result < Transaction , ( ) > {
1386+ let ( mut psbt, expected_max_weight) = SpendableOutputDescriptor :: create_spendable_outputs_psbt ( descriptors, outputs, change_destination_script, feerate_sat_per_1000_weight, locktime) ?;
1387+ self . sign_spendable_outputs_psbt ( descriptors, & mut psbt, secp_ctx) ?;
1388+
1389+ let spend_tx = psbt. extract_tx ( ) ;
1390+
13021391 debug_assert ! ( expected_max_weight >= spend_tx. weight( ) ) ;
13031392 // Note that witnesses with a signature vary somewhat in size, so allow
13041393 // `expected_max_weight` to overshoot by up to 3 bytes per input.
@@ -1512,8 +1601,8 @@ impl PhantomKeysManager {
15121601 }
15131602
15141603 /// See [`KeysManager::spend_spendable_outputs`] for documentation on this method.
1515- pub fn spend_spendable_outputs < C : Signing > ( & self , descriptors : & [ & SpendableOutputDescriptor ] , outputs : Vec < TxOut > , change_destination_script : Script , feerate_sat_per_1000_weight : u32 , secp_ctx : & Secp256k1 < C > ) -> Result < Transaction , ( ) > {
1516- self . inner . spend_spendable_outputs ( descriptors, outputs, change_destination_script, feerate_sat_per_1000_weight, secp_ctx)
1604+ pub fn spend_spendable_outputs < C : Signing > ( & self , descriptors : & [ & SpendableOutputDescriptor ] , outputs : Vec < TxOut > , change_destination_script : Script , feerate_sat_per_1000_weight : u32 , locktime : Option < PackedLockTime > , secp_ctx : & Secp256k1 < C > ) -> Result < Transaction , ( ) > {
1605+ self . inner . spend_spendable_outputs ( descriptors, outputs, change_destination_script, feerate_sat_per_1000_weight, locktime , secp_ctx)
15171606 }
15181607
15191608 /// See [`KeysManager::derive_channel_keys`] for documentation on this method.
0 commit comments