@@ -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,108 @@ impl_writeable_tlv_based_enum!(SpendableOutputDescriptor,
218219 ( 2 , StaticPaymentOutput ) ,
219220) ;
220221
222+ impl SpendableOutputDescriptor {
223+ /// Creates an unsigned [`PartiallySignedTransaction`] which spends the given descriptors to
224+ /// the given outputs, plus an output to the given change destination (if sufficient
225+ /// change value remains). The PSBT will have a feerate, at least, of the given value.
226+ ///
227+ /// Returns the PSBT and expected max transaction weight.
228+ ///
229+ /// Returns `Err(())` if the output value is greater than the input value minus required fee,
230+ /// if a descriptor was duplicated, or if an output descriptor `script_pubkey`
231+ /// does not match the one we can spend.
232+ ///
233+ /// We do not enforce that outputs meet the dust limit or that any output scripts are standard.
234+ pub fn create_spendable_outputs_psbt ( descriptors : & [ & SpendableOutputDescriptor ] , outputs : Vec < TxOut > , change_destination_script : Script , feerate_sat_per_1000_weight : u32 ) -> Result < ( PartiallySignedTransaction , usize ) , ( ) > {
235+ let mut input = Vec :: with_capacity ( descriptors. len ( ) ) ;
236+ let mut psbt_inputs = Vec :: with_capacity ( descriptors. len ( ) ) ;
237+ let mut input_value = 0 ;
238+ let mut witness_weight = 0 ;
239+ let mut output_set = HashSet :: with_capacity ( descriptors. len ( ) ) ;
240+ for outp in descriptors {
241+ match outp {
242+ SpendableOutputDescriptor :: StaticPaymentOutput ( descriptor) => {
243+ input. push ( TxIn {
244+ previous_output : descriptor. outpoint . into_bitcoin_outpoint ( ) ,
245+ script_sig : Script :: new ( ) ,
246+ sequence : Sequence :: ZERO ,
247+ witness : Witness :: new ( ) ,
248+ } ) ;
249+ witness_weight += StaticPaymentOutputDescriptor :: MAX_WITNESS_LENGTH ;
250+ #[ cfg( feature = "grind_signatures" ) ]
251+ { witness_weight -= 1 ; } // Guarantees a low R signature
252+ input_value += descriptor. output . value ;
253+ if !output_set. insert ( descriptor. outpoint ) { return Err ( ( ) ) ; }
254+
255+ // Todo we could add the witness script as well
256+ psbt_inputs. push ( bitcoin:: psbt:: Input {
257+ witness_utxo : Some ( descriptor. output . clone ( ) ) ,
258+ ..Default :: default ( )
259+ } )
260+ } ,
261+ SpendableOutputDescriptor :: DelayedPaymentOutput ( descriptor) => {
262+ input. push ( TxIn {
263+ previous_output : descriptor. outpoint . into_bitcoin_outpoint ( ) ,
264+ script_sig : Script :: new ( ) ,
265+ sequence : Sequence ( descriptor. to_self_delay as u32 ) ,
266+ witness : Witness :: new ( ) ,
267+ } ) ;
268+ witness_weight += DelayedPaymentOutputDescriptor :: MAX_WITNESS_LENGTH ;
269+ #[ cfg( feature = "grind_signatures" ) ]
270+ { witness_weight -= 1 ; } // Guarantees a low R signature
271+ input_value += descriptor. output . value ;
272+ if !output_set. insert ( descriptor. outpoint ) { return Err ( ( ) ) ; }
273+
274+ // Todo we could add the witness script as well
275+ psbt_inputs. push ( bitcoin:: psbt:: Input {
276+ witness_utxo : Some ( descriptor. output . clone ( ) ) ,
277+ ..Default :: default ( )
278+ } )
279+ } ,
280+ SpendableOutputDescriptor :: StaticOutput { ref outpoint, ref output } => {
281+ input. push ( TxIn {
282+ previous_output : outpoint. into_bitcoin_outpoint ( ) ,
283+ script_sig : Script :: new ( ) ,
284+ sequence : Sequence :: ZERO ,
285+ witness : Witness :: new ( ) ,
286+ } ) ;
287+ witness_weight += 1 + 73 + 34 ;
288+ #[ cfg( feature = "grind_signatures" ) ]
289+ { witness_weight -= 1 ; } // Guarantees a low R signature
290+ input_value += output. value ;
291+ if !output_set. insert ( * outpoint) { return Err ( ( ) ) ; }
292+
293+ // Is standard P2WPKH, no need for witness script
294+ psbt_inputs. push ( bitcoin:: psbt:: Input {
295+ witness_utxo : Some ( output. clone ( ) ) ,
296+ ..Default :: default ( )
297+ } )
298+ }
299+ }
300+ if input_value > MAX_VALUE_MSAT / 1000 { return Err ( ( ) ) ; }
301+ }
302+ let mut tx = Transaction {
303+ version : 2 ,
304+ lock_time : PackedLockTime ( 0 ) ,
305+ input,
306+ output : outputs,
307+ } ;
308+ let expected_max_weight =
309+ transaction_utils:: maybe_add_change_output ( & mut tx, input_value, witness_weight, feerate_sat_per_1000_weight, change_destination_script) ?;
310+
311+ let psbt = PartiallySignedTransaction {
312+ inputs : psbt_inputs,
313+ outputs : vec ! [ Default :: default ( ) ; tx. output. len( ) ] ,
314+ unsigned_tx : tx,
315+ xpub : Default :: default ( ) ,
316+ version : 0 ,
317+ proprietary : Default :: default ( ) ,
318+ unknown : Default :: default ( ) ,
319+ } ;
320+ Ok ( ( psbt, expected_max_weight) )
321+ }
322+ }
323+
221324/// A trait to handle Lightning channel key material without concretizing the channel type or
222325/// the signature mechanism.
223326pub trait ChannelSigner {
@@ -1171,97 +1274,40 @@ impl KeysManager {
11711274 )
11721275 }
11731276
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 .
1277+ /// Signs the given [`PartiallySignedTransaction `] which spends the given [`SpendableOutputDescriptor`]s.
1278+ /// The resulting inputs will be finalized and the PSBT will be ready for broadcast if there
1279+ /// are no other inputs that need signing .
11771280 ///
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.
1281+ /// Returns `Err(())` if the PSBT is missing a descriptor or if we fail to sign.
11831282 ///
11841283 /// May panic if the [`SpendableOutputDescriptor`]s were not generated by channels which used
11851284 /// 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-
1285+ pub fn sign_spendable_outputs_psbt < C : Signing > ( & self , descriptors : & [ & SpendableOutputDescriptor ] , psbt : & mut PartiallySignedTransaction , secp_ctx : & Secp256k1 < C > ) -> Result < ( ) , ( ) > {
12441286 let mut keys_cache: Option < ( InMemorySigner , [ u8 ; 32 ] ) > = None ;
1245- let mut input_idx = 0 ;
12461287 for outp in descriptors {
12471288 match outp {
12481289 SpendableOutputDescriptor :: StaticPaymentOutput ( descriptor) => {
1290+ let input_idx = psbt. unsigned_tx . input . iter ( ) . position ( |i| i. previous_output == descriptor. outpoint . into_bitcoin_outpoint ( ) ) . ok_or ( ( ) ) ?;
12491291 if keys_cache. is_none ( ) || keys_cache. as_ref ( ) . unwrap ( ) . 1 != descriptor. channel_keys_id {
12501292 keys_cache = Some ( (
12511293 self . derive_channel_keys ( descriptor. channel_value_satoshis , & descriptor. channel_keys_id ) ,
12521294 descriptor. channel_keys_id ) ) ;
12531295 }
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) ?) ;
1296+ let witness = Witness :: from_vec ( keys_cache. as_ref ( ) . unwrap ( ) . 0 . sign_counterparty_payment_input ( & psbt. unsigned_tx , input_idx, & descriptor, & secp_ctx) ?) ;
1297+ psbt. inputs [ input_idx] . final_script_witness = Some ( witness) ;
12551298 } ,
12561299 SpendableOutputDescriptor :: DelayedPaymentOutput ( descriptor) => {
1300+ let input_idx = psbt. unsigned_tx . input . iter ( ) . position ( |i| i. previous_output == descriptor. outpoint . into_bitcoin_outpoint ( ) ) . ok_or ( ( ) ) ?;
12571301 if keys_cache. is_none ( ) || keys_cache. as_ref ( ) . unwrap ( ) . 1 != descriptor. channel_keys_id {
12581302 keys_cache = Some ( (
12591303 self . derive_channel_keys ( descriptor. channel_value_satoshis , & descriptor. channel_keys_id ) ,
12601304 descriptor. channel_keys_id ) ) ;
12611305 }
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) ?) ;
1306+ let witness = Witness :: from_vec ( keys_cache. as_ref ( ) . unwrap ( ) . 0 . sign_dynamic_p2wsh_input ( & psbt. unsigned_tx , input_idx, & descriptor, & secp_ctx) ?) ;
1307+ psbt. inputs [ input_idx] . final_script_witness = Some ( witness) ;
12631308 } ,
1264- SpendableOutputDescriptor :: StaticOutput { ref output, .. } => {
1309+ SpendableOutputDescriptor :: StaticOutput { ref outpoint, ref output } => {
1310+ let input_idx = psbt. unsigned_tx . input . iter ( ) . position ( |i| i. previous_output == outpoint. into_bitcoin_outpoint ( ) ) . ok_or ( ( ) ) ?;
12651311 let derivation_idx = if output. script_pubkey == self . destination_script {
12661312 1
12671313 } else {
@@ -1288,17 +1334,37 @@ impl KeysManager {
12881334
12891335 if payment_script != output. script_pubkey { return Err ( ( ) ) ; } ;
12901336
1291- let sighash = hash_to_message ! ( & sighash:: SighashCache :: new( & spend_tx ) . segwit_signature_hash( input_idx, & witness_script, output. value, EcdsaSighashType :: All ) . unwrap( ) [ ..] ) ;
1337+ let sighash = hash_to_message ! ( & sighash:: SighashCache :: new( & psbt . unsigned_tx ) . segwit_signature_hash( input_idx, & witness_script, output. value, EcdsaSighashType :: All ) . unwrap( ) [ ..] ) ;
12921338 let sig = sign_with_aux_rand ( secp_ctx, & sighash, & secret. private_key , & self ) ;
12931339 let mut sig_ser = sig. serialize_der ( ) . to_vec ( ) ;
12941340 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 ( ) ) ;
1341+ let witness = Witness :: from_vec ( vec ! [ sig_ser , pubkey . inner . serialize ( ) . to_vec ( ) ] ) ;
1342+ psbt . inputs [ input_idx] . final_script_witness = Some ( witness ) ;
12971343 } ,
12981344 }
1299- input_idx += 1 ;
13001345 }
13011346
1347+ Ok ( ( ) )
1348+ }
1349+
1350+ /// Creates a [`Transaction`] which spends the given descriptors to the given outputs, plus an
1351+ /// output to the given change destination (if sufficient change value remains). The
1352+ /// transaction will have a feerate, at least, of the given value.
1353+ ///
1354+ /// Returns `Err(())` if the output value is greater than the input value minus required fee,
1355+ /// if a descriptor was duplicated, or if an output descriptor `script_pubkey`
1356+ /// does not match the one we can spend.
1357+ ///
1358+ /// We do not enforce that outputs meet the dust limit or that any output scripts are standard.
1359+ ///
1360+ /// May panic if the [`SpendableOutputDescriptor`]s were not generated by channels which used
1361+ /// this [`KeysManager`] or one of the [`InMemorySigner`] created by this [`KeysManager`].
1362+ 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 , ( ) > {
1363+ let ( mut psbt, expected_max_weight) = SpendableOutputDescriptor :: create_spendable_outputs_psbt ( descriptors, outputs, change_destination_script, feerate_sat_per_1000_weight) ?;
1364+ self . sign_spendable_outputs_psbt ( descriptors, & mut psbt, secp_ctx) ?;
1365+
1366+ let spend_tx = psbt. extract_tx ( ) ;
1367+
13021368 debug_assert ! ( expected_max_weight >= spend_tx. weight( ) ) ;
13031369 // Note that witnesses with a signature vary somewhat in size, so allow
13041370 // `expected_max_weight` to overshoot by up to 3 bytes per input.
0 commit comments