Skip to content

Commit d6a8d2c

Browse files
committed
Implement Script for Witness and Add Tweak in Partially Signed Bitcoin Transaction to make it a single data source needed for a Signer to produce valid signatures.
1 parent c2bbfff commit d6a8d2c

File tree

1 file changed

+50
-9
lines changed

1 file changed

+50
-9
lines changed

lightning/src/sign/mod.rs

Lines changed: 50 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use bitcoin::blockdata::script::{Script, ScriptBuf, Builder};
1818
use bitcoin::blockdata::opcodes;
1919
use bitcoin::ecdsa::Signature as EcdsaSignature;
2020
use bitcoin::network::constants::Network;
21-
use bitcoin::psbt::PartiallySignedTransaction;
21+
use bitcoin::psbt::{PartiallySignedTransaction, raw};
2222
use bitcoin::bip32::{ExtendedPrivKey, ExtendedPubKey, ChildNumber};
2323
use bitcoin::sighash;
2424
use bitcoin::sighash::EcdsaSighashType;
@@ -43,7 +43,7 @@ use crate::util::ser::{Writeable, Writer, Readable, ReadableArgs};
4343
use crate::chain::transaction::OutPoint;
4444
use crate::ln::channel::ANCHOR_OUTPUT_VALUE_SATOSHI;
4545
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};
4747
use crate::ln::channel_keys::{DelayedPaymentBasepoint, DelayedPaymentKey, HtlcKey, HtlcBasepoint, RevocationKey, RevocationBasepoint};
4848
use crate::ln::msgs::{UnsignedChannelAnnouncement, UnsignedGossipMessage};
4949
#[cfg(taproot)]
@@ -149,6 +149,7 @@ pub struct StaticPaymentOutputDescriptor {
149149
/// Added as optional, but always `Some` if the descriptor was produced in v0.0.117 or later.
150150
pub channel_transaction_parameters: Option<ChannelTransactionParameters>,
151151
}
152+
152153
impl StaticPaymentOutputDescriptor {
153154
/// Returns the `witness_script` of the spendable output.
154155
///
@@ -304,7 +305,7 @@ impl SpendableOutputDescriptor {
304305
///
305306
/// This is not exported to bindings users as there is no standard serialization for an input.
306307
/// 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 {
308309
match self {
309310
SpendableOutputDescriptor::StaticOutput { output, .. } => {
310311
// Is a standard P2WPKH, no need for witness script
@@ -314,14 +315,25 @@ impl SpendableOutputDescriptor {
314315
}
315316
},
316317
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+
});
318330
bitcoin::psbt::Input {
319331
witness_utxo: Some(descriptor.output.clone()),
332+
witness_script: witness_script,
320333
..Default::default()
321334
}
322335
},
323336
SpendableOutputDescriptor::StaticPaymentOutput(descriptor) => {
324-
// TODO we could add the witness script as well
325337
bitcoin::psbt::Input {
326338
witness_utxo: Some(descriptor.output.clone()),
327339
..Default::default()
@@ -330,6 +342,7 @@ impl SpendableOutputDescriptor {
330342
}
331343
}
332344

345+
333346
/// Creates an unsigned [`PartiallySignedTransaction`] which spends the given descriptors to
334347
/// the given outputs, plus an output to the given change destination (if sufficient
335348
/// change value remains). The PSBT will have a feerate, at least, of the given value.
@@ -346,11 +359,14 @@ impl SpendableOutputDescriptor {
346359
/// does not match the one we can spend.
347360
///
348361
/// 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), ()> {
362+
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), ()> {
363+
let secp_ctx = Secp256k1::new();
350364
let mut input = Vec::with_capacity(descriptors.len());
351365
let mut input_value = 0;
352366
let mut witness_weight = 0;
353367
let mut output_set = HashSet::with_capacity(descriptors.len());
368+
// Required to derive signing key: privkey = basepoint_secret + SHA256(per_commitment_point || basepoint)
369+
let mut add_tweak: Option<Vec<u8>> = None;
354370
for outp in descriptors {
355371
match outp {
356372
SpendableOutputDescriptor::StaticPaymentOutput(descriptor) => {
@@ -387,6 +403,8 @@ impl SpendableOutputDescriptor {
387403
#[cfg(feature = "grind_signatures")]
388404
{ witness_weight -= 1; } // Guarantees a low R signature
389405
input_value += descriptor.output.value;
406+
407+
add_tweak = delayed_payment_basepoint.and_then(|basepoint| Some(derive_add_tweak(&descriptor.per_commitment_point, &basepoint)));
390408
},
391409
SpendableOutputDescriptor::StaticOutput { ref outpoint, ref output, .. } => {
392410
if !output_set.insert(*outpoint) { return Err(()); }
@@ -413,20 +431,43 @@ impl SpendableOutputDescriptor {
413431
let expected_max_weight =
414432
transaction_utils::maybe_add_change_output(&mut tx, input_value, witness_weight, feerate_sat_per_1000_weight, change_destination_script)?;
415433

416-
let psbt_inputs = descriptors.iter().map(|d| d.to_psbt_input()).collect::<Vec<_>>();
434+
let psbt_inputs = descriptors.iter().map(|d| d.to_psbt_input(&secp_ctx, delayed_payment_basepoint)).collect::<Vec<_>>();
417435
let psbt = PartiallySignedTransaction {
418436
inputs: psbt_inputs,
419437
outputs: vec![Default::default(); tx.output.len()],
420438
unsigned_tx: tx,
421439
xpub: Default::default(),
422440
version: 0,
423-
proprietary: Default::default(),
441+
proprietary: add_tweak.map(|add_tweak| {vec![(
442+
raw::ProprietaryKey {
443+
prefix: "spendable_output".as_bytes().to_vec(),
444+
subtype: 0,
445+
key: "add_tweak".as_bytes().to_vec(),
446+
},
447+
add_tweak,
448+
)].into_iter().collect()}).or(Some(Default::default())).expect("proprietary fields"),
424449
unknown: Default::default(),
425450
};
426451
Ok((psbt, expected_max_weight))
427452
}
428453
}
429454

455+
/// Derives a per-commitment-transaction (eg an htlc key or delayed_payment key) private key addition tweak
456+
/// from a delayed payment basepoint and a per_commitment_point:
457+
/// `privkey = basepoint_secret + SHA256(per_commitment_point || basepoint)`
458+
/// TODO(oleg): refactor after migration to LDK v119
459+
pub fn derive_add_tweak(
460+
per_commitment_point: &PublicKey,
461+
basepoint: &DelayedPaymentBasepoint,
462+
) -> Vec<u8> {
463+
let mut sha = Sha256::engine();
464+
sha.input(&per_commitment_point.serialize());
465+
sha.input(&basepoint.to_public_key().serialize());
466+
let res = Sha256::from_engine(sha).to_byte_array();
467+
res.to_vec()
468+
}
469+
470+
430471
/// The parameters required to derive a channel signer via [`SignerProvider`].
431472
#[derive(Clone, Debug, PartialEq, Eq)]
432473
pub struct ChannelDerivationParameters {
@@ -1615,7 +1656,7 @@ impl KeysManager {
16151656
/// May panic if the [`SpendableOutputDescriptor`]s were not generated by channels which used
16161657
/// this [`KeysManager`] or one of the [`InMemorySigner`] created by this [`KeysManager`].
16171658
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)?;
1659+
let (mut psbt, expected_max_weight) = SpendableOutputDescriptor::create_spendable_outputs_psbt(descriptors, outputs, change_destination_script, feerate_sat_per_1000_weight, locktime, None)?;
16191660
psbt = self.sign_spendable_outputs_psbt(descriptors, psbt, secp_ctx)?;
16201661

16211662
let spend_tx = psbt.extract_tx();

0 commit comments

Comments
 (0)