@@ -47,6 +47,7 @@ use crate::prelude::*;
4747use core:: convert:: TryInto ;
4848use core:: ops:: Deref ;
4949use core:: sync:: atomic:: { AtomicUsize , Ordering } ;
50+ use bitcoin:: psbt:: PartiallySignedTransaction ;
5051use crate :: io:: { self , Error } ;
5152use crate :: ln:: msgs:: { DecodeError , MAX_VALUE_MSAT } ;
5253use crate :: util:: atomic_counter:: AtomicCounter ;
@@ -218,6 +219,121 @@ 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+ /// Returns the PSBT and expected max transaction weight.
259+ ///
260+ /// Returns `Err(())` if the output value is greater than the input value minus required fee,
261+ /// if a descriptor was duplicated, or if an output descriptor `script_pubkey`
262+ /// does not match the one we can spend.
263+ ///
264+ /// We do not enforce that outputs meet the dust limit or that any output scripts are standard.
265+ 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 ) , ( ) > {
266+ let mut input = Vec :: with_capacity ( descriptors. len ( ) ) ;
267+ let mut input_value = 0 ;
268+ let mut witness_weight = 0 ;
269+ let mut output_set = HashSet :: with_capacity ( descriptors. len ( ) ) ;
270+ for outp in descriptors {
271+ match outp {
272+ SpendableOutputDescriptor :: StaticPaymentOutput ( descriptor) => {
273+ if !output_set. insert ( descriptor. outpoint ) { return Err ( ( ) ) ; }
274+ input. push ( TxIn {
275+ previous_output : descriptor. outpoint . into_bitcoin_outpoint ( ) ,
276+ script_sig : Script :: new ( ) ,
277+ sequence : Sequence :: ZERO ,
278+ witness : Witness :: new ( ) ,
279+ } ) ;
280+ witness_weight += StaticPaymentOutputDescriptor :: MAX_WITNESS_LENGTH ;
281+ #[ cfg( feature = "grind_signatures" ) ]
282+ { witness_weight -= 1 ; } // Guarantees a low R signature
283+ input_value += descriptor. output . value ;
284+ } ,
285+ SpendableOutputDescriptor :: DelayedPaymentOutput ( descriptor) => {
286+ if !output_set. insert ( descriptor. outpoint ) { return Err ( ( ) ) ; }
287+ input. push ( TxIn {
288+ previous_output : descriptor. outpoint . into_bitcoin_outpoint ( ) ,
289+ script_sig : Script :: new ( ) ,
290+ sequence : Sequence ( descriptor. to_self_delay as u32 ) ,
291+ witness : Witness :: new ( ) ,
292+ } ) ;
293+ witness_weight += DelayedPaymentOutputDescriptor :: MAX_WITNESS_LENGTH ;
294+ #[ cfg( feature = "grind_signatures" ) ]
295+ { witness_weight -= 1 ; } // Guarantees a low R signature
296+ input_value += descriptor. output . value ;
297+ } ,
298+ SpendableOutputDescriptor :: StaticOutput { ref outpoint, ref output } => {
299+ if !output_set. insert ( * outpoint) { return Err ( ( ) ) ; }
300+ input. push ( TxIn {
301+ previous_output : outpoint. into_bitcoin_outpoint ( ) ,
302+ script_sig : Script :: new ( ) ,
303+ sequence : Sequence :: ZERO ,
304+ witness : Witness :: new ( ) ,
305+ } ) ;
306+ witness_weight += 1 + 73 + 34 ;
307+ #[ cfg( feature = "grind_signatures" ) ]
308+ { witness_weight -= 1 ; } // Guarantees a low R signature
309+ input_value += output. value ;
310+ }
311+ }
312+ if input_value > MAX_VALUE_MSAT / 1000 { return Err ( ( ) ) ; }
313+ }
314+ let mut tx = Transaction {
315+ version : 2 ,
316+ lock_time : locktime. unwrap_or ( PackedLockTime :: ZERO ) ,
317+ input,
318+ output : outputs,
319+ } ;
320+ let expected_max_weight =
321+ transaction_utils:: maybe_add_change_output ( & mut tx, input_value, witness_weight, feerate_sat_per_1000_weight, change_destination_script) ?;
322+
323+ let psbt_inputs = descriptors. iter ( ) . map ( |d| d. to_psbt_input ( ) ) . collect :: < Vec < _ > > ( ) ;
324+ let psbt = PartiallySignedTransaction {
325+ inputs : psbt_inputs,
326+ outputs : vec ! [ Default :: default ( ) ; tx. output. len( ) ] ,
327+ unsigned_tx : tx,
328+ xpub : Default :: default ( ) ,
329+ version : 0 ,
330+ proprietary : Default :: default ( ) ,
331+ unknown : Default :: default ( ) ,
332+ } ;
333+ Ok ( ( psbt, expected_max_weight) )
334+ }
335+ }
336+
221337/// A trait to handle Lightning channel key material without concretizing the channel type or
222338/// the signature mechanism.
223339pub trait ChannelSigner {
@@ -1171,97 +1287,40 @@ impl KeysManager {
11711287 )
11721288 }
11731289
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 .
1290+ /// Signs the given [`PartiallySignedTransaction `] which spends the given [`SpendableOutputDescriptor`]s.
1291+ /// The resulting inputs will be finalized and the PSBT will be ready for broadcast if there
1292+ /// are no other inputs that need signing .
11771293 ///
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.
1294+ /// Returns `Err(())` if the PSBT is missing a descriptor or if we fail to sign.
11831295 ///
11841296 /// May panic if the [`SpendableOutputDescriptor`]s were not generated by channels which used
11851297 /// 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-
1298+ pub fn sign_spendable_outputs_psbt < C : Signing > ( & self , descriptors : & [ & SpendableOutputDescriptor ] , psbt : & mut PartiallySignedTransaction , secp_ctx : & Secp256k1 < C > ) -> Result < ( ) , ( ) > {
12441299 let mut keys_cache: Option < ( InMemorySigner , [ u8 ; 32 ] ) > = None ;
1245- let mut input_idx = 0 ;
12461300 for outp in descriptors {
12471301 match outp {
12481302 SpendableOutputDescriptor :: StaticPaymentOutput ( descriptor) => {
1303+ let input_idx = psbt. unsigned_tx . input . iter ( ) . position ( |i| i. previous_output == descriptor. outpoint . into_bitcoin_outpoint ( ) ) . ok_or ( ( ) ) ?;
12491304 if keys_cache. is_none ( ) || keys_cache. as_ref ( ) . unwrap ( ) . 1 != descriptor. channel_keys_id {
12501305 keys_cache = Some ( (
12511306 self . derive_channel_keys ( descriptor. channel_value_satoshis , & descriptor. channel_keys_id ) ,
12521307 descriptor. channel_keys_id ) ) ;
12531308 }
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) ?) ;
1309+ let witness = Witness :: from_vec ( keys_cache. as_ref ( ) . unwrap ( ) . 0 . sign_counterparty_payment_input ( & psbt. unsigned_tx , input_idx, & descriptor, & secp_ctx) ?) ;
1310+ psbt. inputs [ input_idx] . final_script_witness = Some ( witness) ;
12551311 } ,
12561312 SpendableOutputDescriptor :: DelayedPaymentOutput ( descriptor) => {
1313+ let input_idx = psbt. unsigned_tx . input . iter ( ) . position ( |i| i. previous_output == descriptor. outpoint . into_bitcoin_outpoint ( ) ) . ok_or ( ( ) ) ?;
12571314 if keys_cache. is_none ( ) || keys_cache. as_ref ( ) . unwrap ( ) . 1 != descriptor. channel_keys_id {
12581315 keys_cache = Some ( (
12591316 self . derive_channel_keys ( descriptor. channel_value_satoshis , & descriptor. channel_keys_id ) ,
12601317 descriptor. channel_keys_id ) ) ;
12611318 }
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) ?) ;
1319+ let witness = Witness :: from_vec ( keys_cache. as_ref ( ) . unwrap ( ) . 0 . sign_dynamic_p2wsh_input ( & psbt. unsigned_tx , input_idx, & descriptor, & secp_ctx) ?) ;
1320+ psbt. inputs [ input_idx] . final_script_witness = Some ( witness) ;
12631321 } ,
1264- SpendableOutputDescriptor :: StaticOutput { ref output, .. } => {
1322+ SpendableOutputDescriptor :: StaticOutput { ref outpoint, ref output } => {
1323+ let input_idx = psbt. unsigned_tx . input . iter ( ) . position ( |i| i. previous_output == outpoint. into_bitcoin_outpoint ( ) ) . ok_or ( ( ) ) ?;
12651324 let derivation_idx = if output. script_pubkey == self . destination_script {
12661325 1
12671326 } else {
@@ -1288,17 +1347,37 @@ impl KeysManager {
12881347
12891348 if payment_script != output. script_pubkey { return Err ( ( ) ) ; } ;
12901349
1291- let sighash = hash_to_message ! ( & sighash:: SighashCache :: new( & spend_tx ) . segwit_signature_hash( input_idx, & witness_script, output. value, EcdsaSighashType :: All ) . unwrap( ) [ ..] ) ;
1350+ let sighash = hash_to_message ! ( & sighash:: SighashCache :: new( & psbt . unsigned_tx ) . segwit_signature_hash( input_idx, & witness_script, output. value, EcdsaSighashType :: All ) . unwrap( ) [ ..] ) ;
12921351 let sig = sign_with_aux_rand ( secp_ctx, & sighash, & secret. private_key , & self ) ;
12931352 let mut sig_ser = sig. serialize_der ( ) . to_vec ( ) ;
12941353 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 ( ) ) ;
1354+ let witness = Witness :: from_vec ( vec ! [ sig_ser , pubkey . inner . serialize ( ) . to_vec ( ) ] ) ;
1355+ psbt . inputs [ input_idx] . final_script_witness = Some ( witness ) ;
12971356 } ,
12981357 }
1299- input_idx += 1 ;
13001358 }
13011359
1360+ Ok ( ( ) )
1361+ }
1362+
1363+ /// Creates a [`Transaction`] which spends the given descriptors to the given outputs, plus an
1364+ /// output to the given change destination (if sufficient change value remains). The
1365+ /// transaction will have a feerate, at least, of the given value.
1366+ ///
1367+ /// Returns `Err(())` if the output value is greater than the input value minus required fee,
1368+ /// if a descriptor was duplicated, or if an output descriptor `script_pubkey`
1369+ /// does not match the one we can spend.
1370+ ///
1371+ /// We do not enforce that outputs meet the dust limit or that any output scripts are standard.
1372+ ///
1373+ /// May panic if the [`SpendableOutputDescriptor`]s were not generated by channels which used
1374+ /// this [`KeysManager`] or one of the [`InMemorySigner`] created by this [`KeysManager`].
1375+ 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 , ( ) > {
1376+ let ( mut psbt, expected_max_weight) = SpendableOutputDescriptor :: create_spendable_outputs_psbt ( descriptors, outputs, change_destination_script, feerate_sat_per_1000_weight, None ) ?;
1377+ self . sign_spendable_outputs_psbt ( descriptors, & mut psbt, secp_ctx) ?;
1378+
1379+ let spend_tx = psbt. extract_tx ( ) ;
1380+
13021381 debug_assert ! ( expected_max_weight >= spend_tx. weight( ) ) ;
13031382 // Note that witnesses with a signature vary somewhat in size, so allow
13041383 // `expected_max_weight` to overshoot by up to 3 bytes per input.
0 commit comments