Skip to content

Commit

Permalink
DelayedPaymentBasepoint is optional in channel monitor file for a spe…
Browse files Browse the repository at this point in the history
…ndable output.

Add Tweak is moved to the input level.
  • Loading branch information
yellowred committed Dec 11, 2023
1 parent d018d1b commit 075ee16
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 43 deletions.
2 changes: 1 addition & 1 deletion lightning/src/chain/channelmonitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4164,7 +4164,7 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitorImpl<Signer> {
revocation_pubkey: broadcasted_holder_revokable_script.2,
channel_keys_id: self.channel_keys_id,
channel_value_satoshis: self.channel_value_satoshis,
delayed_payment_basepoint: self.onchain_tx_handler.signer.pubkeys().delayed_payment_basepoint,
delayed_payment_basepoint: Some(self.onchain_tx_handler.signer.pubkeys().delayed_payment_basepoint),
}));
}
}
Expand Down
15 changes: 15 additions & 0 deletions lightning/src/ln/channel_keys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,21 @@ impl RevocationKey {
key_read_write!(RevocationKey);


/// Derives a per-commitment-transaction (eg an htlc key or delayed_payment key) private key addition tweak
/// from a delayed payment basepoint and a per_commitment_point:
/// `privkey = basepoint_secret + SHA256(per_commitment_point || basepoint)`
/// TODO(oleg): refactor after migration to LDK v119
pub fn derive_add_tweak(
per_commitment_point: &PublicKey,
basepoint: &DelayedPaymentBasepoint,
) -> Vec<u8> {
let mut sha = Sha256::engine();
sha.input(&per_commitment_point.serialize());
sha.input(&basepoint.to_public_key().serialize());
let res = Sha256::from_engine(sha).to_byte_array();
res.to_vec()
}


#[cfg(test)]
mod test {
Expand Down
72 changes: 30 additions & 42 deletions lightning/src/sign/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ use crate::chain::transaction::OutPoint;
use crate::ln::channel::ANCHOR_OUTPUT_VALUE_SATOSHI;
use crate::ln::{chan_utils, PaymentPreimage};
use crate::ln::chan_utils::{HTLCOutputInCommitment, make_funding_redeemscript, ChannelPublicKeys, HolderCommitmentTransaction, ChannelTransactionParameters, CommitmentTransaction, ClosingTransaction, get_revokeable_redeemscript};
use crate::ln::channel_keys::{DelayedPaymentBasepoint, DelayedPaymentKey, HtlcKey, HtlcBasepoint, RevocationKey, RevocationBasepoint};
use crate::ln::channel_keys::{DelayedPaymentBasepoint, DelayedPaymentKey, HtlcKey, HtlcBasepoint, RevocationKey, RevocationBasepoint, derive_add_tweak};
use crate::ln::msgs::{UnsignedChannelAnnouncement, UnsignedGossipMessage};
#[cfg(taproot)]
use crate::ln::msgs::PartialSignatureWithNonce;
Expand Down Expand Up @@ -104,7 +104,7 @@ pub struct DelayedPaymentOutputDescriptor {
/// The value of the channel which this output originated from, possibly indirectly.
pub channel_value_satoshis: u64,
/// Channel base key used to generate a witness data to spend this output.
pub delayed_payment_basepoint: DelayedPaymentBasepoint
pub delayed_payment_basepoint: Option<DelayedPaymentBasepoint>
}

impl DelayedPaymentOutputDescriptor {
Expand All @@ -124,7 +124,7 @@ impl_writeable_tlv_based!(DelayedPaymentOutputDescriptor, {
(8, revocation_pubkey, required),
(10, channel_keys_id, required),
(12, channel_value_satoshis, required),
(14, delayed_payment_basepoint, required),
(14, delayed_payment_basepoint, option),
});

pub(crate) const P2WPKH_WITNESS_WEIGHT: u64 = 1 /* num stack items */ +
Expand Down Expand Up @@ -319,21 +319,35 @@ impl SpendableOutputDescriptor {
}
},
SpendableOutputDescriptor::DelayedPaymentOutput(descriptor) => {
let witness_script = {
let payment_key = DelayedPaymentKey::from_basepoint(
secp_ctx,
&descriptor.delayed_payment_basepoint,
&descriptor.per_commitment_point,
);
get_revokeable_redeemscript(
&descriptor.revocation_pubkey,
descriptor.to_self_delay,
&payment_key,
)
let (witness_script, add_tweak) = if let Some(basepoint) = descriptor.delayed_payment_basepoint.as_ref() {
let payment_key = DelayedPaymentKey::from_basepoint(
secp_ctx,
basepoint,
&descriptor.per_commitment_point,
);
// Required to derive signing key: privkey = basepoint_secret + SHA256(per_commitment_point || basepoint)
let add_tweak = derive_add_tweak(&descriptor.per_commitment_point, basepoint);
(Some(get_revokeable_redeemscript(
&descriptor.revocation_pubkey,
descriptor.to_self_delay,
&payment_key,
)), Some(add_tweak))
} else {
(None, None)
};


bitcoin::psbt::Input {
witness_utxo: Some(descriptor.output.clone()),
witness_script: Some(witness_script),
witness_script,
proprietary: add_tweak.map(|add_tweak| {vec![(
raw::ProprietaryKey {
prefix: "LDK_spendable_output".as_bytes().to_vec(),
subtype: 0,
key: "add_tweak".as_bytes().to_vec(),
},
add_tweak,
)].into_iter().collect()}).unwrap_or_default(),
..Default::default()
}
},
Expand Down Expand Up @@ -370,8 +384,6 @@ impl SpendableOutputDescriptor {
let mut input_value = 0;
let mut witness_weight = 0;
let mut output_set = HashSet::with_capacity(descriptors.len());
// Required to derive signing key: privkey = basepoint_secret + SHA256(per_commitment_point || basepoint)
let mut add_tweak: Option<Vec<u8>> = None;
for outp in descriptors {
match outp {
SpendableOutputDescriptor::StaticPaymentOutput(descriptor) => {
Expand Down Expand Up @@ -408,8 +420,6 @@ impl SpendableOutputDescriptor {
#[cfg(feature = "grind_signatures")]
{ witness_weight -= 1; } // Guarantees a low R signature
input_value += descriptor.output.value;

add_tweak = Some(derive_add_tweak(&descriptor.per_commitment_point, &descriptor.delayed_payment_basepoint));
},
SpendableOutputDescriptor::StaticOutput { ref outpoint, ref output, .. } => {
if !output_set.insert(*outpoint) { return Err(()); }
Expand Down Expand Up @@ -443,35 +453,13 @@ impl SpendableOutputDescriptor {
unsigned_tx: tx,
xpub: Default::default(),
version: 0,
proprietary: add_tweak.map(|add_tweak| {vec![(
raw::ProprietaryKey {
prefix: "spendable_output".as_bytes().to_vec(),
subtype: 0,
key: "add_tweak".as_bytes().to_vec(),
},
add_tweak,
)].into_iter().collect()}).unwrap_or_default(),
proprietary: Default::default(),
unknown: Default::default(),
};
Ok((psbt, expected_max_weight))
}
}

/// Derives a per-commitment-transaction (eg an htlc key or delayed_payment key) private key addition tweak
/// from a delayed payment basepoint and a per_commitment_point:
/// `privkey = basepoint_secret + SHA256(per_commitment_point || basepoint)`
/// TODO(oleg): refactor after migration to LDK v119
pub fn derive_add_tweak(
per_commitment_point: &PublicKey,
basepoint: &DelayedPaymentBasepoint,
) -> Vec<u8> {
let mut sha = Sha256::engine();
sha.input(&per_commitment_point.serialize());
sha.input(&basepoint.to_public_key().serialize());
let res = Sha256::from_engine(sha).to_byte_array();
res.to_vec()
}


/// The parameters required to derive a channel signer via [`SignerProvider`].
#[derive(Clone, Debug, PartialEq, Eq)]
Expand Down

0 comments on commit 075ee16

Please sign in to comment.