@@ -18,7 +18,7 @@ use bitcoin::blockdata::script::{Script, ScriptBuf, Builder};
18
18
use bitcoin:: blockdata:: opcodes;
19
19
use bitcoin:: ecdsa:: Signature as EcdsaSignature ;
20
20
use bitcoin:: network:: constants:: Network ;
21
- use bitcoin:: psbt:: PartiallySignedTransaction ;
21
+ use bitcoin:: psbt:: { PartiallySignedTransaction , raw } ;
22
22
use bitcoin:: bip32:: { ExtendedPrivKey , ExtendedPubKey , ChildNumber } ;
23
23
use bitcoin:: sighash;
24
24
use bitcoin:: sighash:: EcdsaSighashType ;
@@ -43,7 +43,7 @@ use crate::util::ser::{Writeable, Writer, Readable, ReadableArgs};
43
43
use crate :: chain:: transaction:: OutPoint ;
44
44
use crate :: ln:: channel:: ANCHOR_OUTPUT_VALUE_SATOSHI ;
45
45
use crate :: ln:: { chan_utils, PaymentPreimage } ;
46
- use crate :: ln:: chan_utils:: { HTLCOutputInCommitment , make_funding_redeemscript, ChannelPublicKeys , HolderCommitmentTransaction , ChannelTransactionParameters , CommitmentTransaction , ClosingTransaction } ;
46
+ use crate :: ln:: chan_utils:: { HTLCOutputInCommitment , make_funding_redeemscript, ChannelPublicKeys , HolderCommitmentTransaction , ChannelTransactionParameters , CommitmentTransaction , ClosingTransaction , get_revokeable_redeemscript } ;
47
47
use crate :: ln:: channel_keys:: { DelayedPaymentBasepoint , DelayedPaymentKey , HtlcKey , HtlcBasepoint , RevocationKey , RevocationBasepoint } ;
48
48
use crate :: ln:: msgs:: { UnsignedChannelAnnouncement , UnsignedGossipMessage } ;
49
49
#[ cfg( taproot) ]
@@ -149,6 +149,7 @@ pub struct StaticPaymentOutputDescriptor {
149
149
/// Added as optional, but always `Some` if the descriptor was produced in v0.0.117 or later.
150
150
pub channel_transaction_parameters : Option < ChannelTransactionParameters > ,
151
151
}
152
+
152
153
impl StaticPaymentOutputDescriptor {
153
154
/// Returns the `witness_script` of the spendable output.
154
155
///
@@ -304,7 +305,7 @@ impl SpendableOutputDescriptor {
304
305
///
305
306
/// This is not exported to bindings users as there is no standard serialization for an input.
306
307
/// See [`Self::create_spendable_outputs_psbt`] instead.
307
- pub fn to_psbt_input ( & self ) -> bitcoin:: psbt:: Input {
308
+ pub fn to_psbt_input < T : secp256k1 :: Signing > ( & self , secp_ctx : & Secp256k1 < T > , delayed_payment_basepoint : Option < & DelayedPaymentBasepoint > ) -> bitcoin:: psbt:: Input {
308
309
match self {
309
310
SpendableOutputDescriptor :: StaticOutput { output, .. } => {
310
311
// Is a standard P2WPKH, no need for witness script
@@ -314,9 +315,21 @@ impl SpendableOutputDescriptor {
314
315
}
315
316
} ,
316
317
SpendableOutputDescriptor :: DelayedPaymentOutput ( descriptor) => {
317
- // TODO we could add the witness script as well
318
+ let witness_script = delayed_payment_basepoint. map ( |basepoint| {
319
+ let payment_key = DelayedPaymentKey :: from_basepoint (
320
+ secp_ctx,
321
+ basepoint,
322
+ & descriptor. per_commitment_point ,
323
+ ) ;
324
+ get_revokeable_redeemscript (
325
+ & descriptor. revocation_pubkey ,
326
+ descriptor. to_self_delay ,
327
+ & payment_key,
328
+ )
329
+ } ) ;
318
330
bitcoin:: psbt:: Input {
319
331
witness_utxo : Some ( descriptor. output . clone ( ) ) ,
332
+ witness_script : witness_script,
320
333
..Default :: default ( )
321
334
}
322
335
} ,
@@ -330,6 +343,7 @@ impl SpendableOutputDescriptor {
330
343
}
331
344
}
332
345
346
+
333
347
/// Creates an unsigned [`PartiallySignedTransaction`] which spends the given descriptors to
334
348
/// the given outputs, plus an output to the given change destination (if sufficient
335
349
/// change value remains). The PSBT will have a feerate, at least, of the given value.
@@ -346,11 +360,14 @@ impl SpendableOutputDescriptor {
346
360
/// does not match the one we can spend.
347
361
///
348
362
/// We do not enforce that outputs meet the dust limit or that any output scripts are standard.
349
- pub fn create_spendable_outputs_psbt ( descriptors : & [ & SpendableOutputDescriptor ] , outputs : Vec < TxOut > , change_destination_script : ScriptBuf , feerate_sat_per_1000_weight : u32 , locktime : Option < LockTime > ) -> Result < ( PartiallySignedTransaction , u64 ) , ( ) > {
363
+ pub fn create_spendable_outputs_psbt ( descriptors : & [ & SpendableOutputDescriptor ] , outputs : Vec < TxOut > , change_destination_script : ScriptBuf , feerate_sat_per_1000_weight : u32 , locktime : Option < LockTime > , delayed_payment_basepoint : Option < & DelayedPaymentBasepoint > ) -> Result < ( PartiallySignedTransaction , u64 ) , ( ) > {
364
+ let secp_ctx = Secp256k1 :: new ( ) ;
350
365
let mut input = Vec :: with_capacity ( descriptors. len ( ) ) ;
351
366
let mut input_value = 0 ;
352
367
let mut witness_weight = 0 ;
353
368
let mut output_set = HashSet :: with_capacity ( descriptors. len ( ) ) ;
369
+ // Required to derive signing key: privkey = basepoint_secret + SHA256(per_commitment_point || basepoint)
370
+ let mut add_tweak: Option < Vec < u8 > > = None ;
354
371
for outp in descriptors {
355
372
match outp {
356
373
SpendableOutputDescriptor :: StaticPaymentOutput ( descriptor) => {
@@ -387,6 +404,8 @@ impl SpendableOutputDescriptor {
387
404
#[ cfg( feature = "grind_signatures" ) ]
388
405
{ witness_weight -= 1 ; } // Guarantees a low R signature
389
406
input_value += descriptor. output . value ;
407
+
408
+ add_tweak = delayed_payment_basepoint. and_then ( |basepoint| Some ( derive_add_tweak ( & descriptor. per_commitment_point , & basepoint) ) ) ;
390
409
} ,
391
410
SpendableOutputDescriptor :: StaticOutput { ref outpoint, ref output, .. } => {
392
411
if !output_set. insert ( * outpoint) { return Err ( ( ) ) ; }
@@ -413,20 +432,43 @@ impl SpendableOutputDescriptor {
413
432
let expected_max_weight =
414
433
transaction_utils:: maybe_add_change_output ( & mut tx, input_value, witness_weight, feerate_sat_per_1000_weight, change_destination_script) ?;
415
434
416
- let psbt_inputs = descriptors. iter ( ) . map ( |d| d. to_psbt_input ( ) ) . collect :: < Vec < _ > > ( ) ;
435
+ let psbt_inputs = descriptors. iter ( ) . map ( |d| d. to_psbt_input ( & secp_ctx , delayed_payment_basepoint ) ) . collect :: < Vec < _ > > ( ) ;
417
436
let psbt = PartiallySignedTransaction {
418
437
inputs : psbt_inputs,
419
438
outputs : vec ! [ Default :: default ( ) ; tx. output. len( ) ] ,
420
439
unsigned_tx : tx,
421
440
xpub : Default :: default ( ) ,
422
441
version : 0 ,
423
- proprietary : Default :: default ( ) ,
442
+ proprietary : add_tweak. map ( |add_tweak| { vec ! [ (
443
+ raw:: ProprietaryKey {
444
+ prefix: "spendable_output" . as_bytes( ) . to_vec( ) ,
445
+ subtype: 0 ,
446
+ key: "add_tweak" . as_bytes( ) . to_vec( ) ,
447
+ } ,
448
+ add_tweak,
449
+ ) ] . into_iter ( ) . collect ( ) } ) . unwrap_or_default ( ) ,
424
450
unknown : Default :: default ( ) ,
425
451
} ;
426
452
Ok ( ( psbt, expected_max_weight) )
427
453
}
428
454
}
429
455
456
+ /// Derives a per-commitment-transaction (eg an htlc key or delayed_payment key) private key addition tweak
457
+ /// from a delayed payment basepoint and a per_commitment_point:
458
+ /// `privkey = basepoint_secret + SHA256(per_commitment_point || basepoint)`
459
+ /// TODO(oleg): refactor after migration to LDK v119
460
+ pub fn derive_add_tweak (
461
+ per_commitment_point : & PublicKey ,
462
+ basepoint : & DelayedPaymentBasepoint ,
463
+ ) -> Vec < u8 > {
464
+ let mut sha = Sha256 :: engine ( ) ;
465
+ sha. input ( & per_commitment_point. serialize ( ) ) ;
466
+ sha. input ( & basepoint. to_public_key ( ) . serialize ( ) ) ;
467
+ let res = Sha256 :: from_engine ( sha) . to_byte_array ( ) ;
468
+ res. to_vec ( )
469
+ }
470
+
471
+
430
472
/// The parameters required to derive a channel signer via [`SignerProvider`].
431
473
#[ derive( Clone , Debug , PartialEq , Eq ) ]
432
474
pub struct ChannelDerivationParameters {
@@ -1615,7 +1657,7 @@ impl KeysManager {
1615
1657
/// May panic if the [`SpendableOutputDescriptor`]s were not generated by channels which used
1616
1658
/// this [`KeysManager`] or one of the [`InMemorySigner`] created by this [`KeysManager`].
1617
1659
pub fn spend_spendable_outputs < C : Signing > ( & self , descriptors : & [ & SpendableOutputDescriptor ] , outputs : Vec < TxOut > , change_destination_script : ScriptBuf , feerate_sat_per_1000_weight : u32 , locktime : Option < LockTime > , secp_ctx : & Secp256k1 < C > ) -> Result < Transaction , ( ) > {
1618
- let ( mut psbt, expected_max_weight) = SpendableOutputDescriptor :: create_spendable_outputs_psbt ( descriptors, outputs, change_destination_script, feerate_sat_per_1000_weight, locktime) ?;
1660
+ let ( mut psbt, expected_max_weight) = SpendableOutputDescriptor :: create_spendable_outputs_psbt ( descriptors, outputs, change_destination_script, feerate_sat_per_1000_weight, locktime, None ) ?;
1619
1661
psbt = self . sign_spendable_outputs_psbt ( descriptors, psbt, secp_ctx) ?;
1620
1662
1621
1663
let spend_tx = psbt. extract_tx ( ) ;
0 commit comments