Skip to content

Commit

Permalink
Handle auto close from LDK
Browse files Browse the repository at this point in the history
  • Loading branch information
Tibo-lg committed Aug 16, 2023
1 parent ac5ac98 commit f8716ae
Show file tree
Hide file tree
Showing 29 changed files with 863 additions and 275 deletions.
6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ members = [
]

[patch.crates-io]
lightning = { git = "https://github.com/p2pderivatives/rust-lightning/", rev = "420d961d" }
lightning-net-tokio = { git = "https://github.com/p2pderivatives/rust-lightning/", rev = "420d961d" }
lightning-persister = { git = "https://github.com/p2pderivatives/rust-lightning/", rev = "420d961d" }
lightning = { git = "https://github.com/p2pderivatives/rust-lightning/", rev = "47c8479" }
lightning-net-tokio = { git = "https://github.com/p2pderivatives/rust-lightning/", rev = "47c8479" }
lightning-persister = { git = "https://github.com/p2pderivatives/rust-lightning/", rev = "47c8479" }
Binary file removed dlc-manager/ClosingSubChannel
Binary file not shown.
Binary file removed dlc-manager/ConfirmedSubChannel
Binary file not shown.
Binary file removed dlc-manager/CounterOnChainClosedSubChannel
Binary file not shown.
Binary file removed dlc-manager/FinalizedSubChannel
Binary file not shown.
Binary file removed dlc-manager/OnChainClosedSubChannel
Binary file not shown.
510 changes: 327 additions & 183 deletions dlc-manager/src/sub_channel_manager.rs

Large diffs are not rendered by default.

134 changes: 104 additions & 30 deletions dlc-manager/src/subchannel/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ use dlc::channel::sub_channel::SplitTx;
use lightning::{
chain::{
chaininterface::{BroadcasterInterface, FeeEstimator},
keysinterface::{EntropySource, NodeSigner, SignerProvider},
chainmonitor::ChainMonitor,
keysinterface::{EntropySource, NodeSigner, SignerProvider, WriteableEcdsaChannelSigner},
Watch,
},
ln::{
chan_utils::CounterpartyCommitmentSecrets,
Expand Down Expand Up @@ -56,6 +58,8 @@ pub struct SubChannel {
pub counter_fund_pk: PublicKey,
/// The revocation secrets from the remote party for already revoked split transactions.
pub counter_party_secrets: CounterpartyCommitmentSecrets,
/// The id used to derive the keys for the Lightning channel.
pub channel_keys_id: [u8; 32],
}

impl std::fmt::Debug for SubChannel {
Expand Down Expand Up @@ -422,11 +426,6 @@ where
revoke_and_ack: &RevokeAndACK,
) -> Result<(), APIError>;

/// Gives the ability to access the funding secret key within the provided callback.
fn sign_with_fund_key_cb<F>(&self, channel_lock: &mut ChannelLock<SP>, cb: &mut F)
where
F: FnMut(&SecretKey);

/// Force close the channel with given `channel_id` and `counter_party_node_id`.
fn force_close_channel(
&self,
Expand All @@ -443,13 +442,26 @@ where
channel_value_satoshis: u64,
value_to_self_msat: u64,
);
}

/// Provides methods to interact with a `ChainMonitor` for a Lightning channel (in particular the
/// one from LDK).
pub trait LNChainMonitor {
/// Gets the latest commitment transactions and HTLC transactions that can be used to close the
/// channel.
fn get_latest_holder_commitment_txn(
&self,
channel_lock: &ChannelLock<SP>,
funding_txo: &lightning::chain::transaction::OutPoint,
) -> Result<Vec<Transaction>, Error>;

/// Updates the funding transaction output of the channel monitor associated with the channel
/// specified by `old_funding_txo`.
fn update_channel_funding_txo(
&self,
old_funding_txo: &lightning::chain::transaction::OutPoint,
new_funding_txo: &lightning::chain::transaction::OutPoint,
channel_value_satoshis: u64,
) -> Result<(), Error>;
}

impl<M: Deref, T: Deref, ES: Deref, NS: Deref, K: Deref, F: Deref, R: Deref, L: Deref>
Expand Down Expand Up @@ -508,16 +520,6 @@ where
self.revoke_and_ack_commitment(channel_lock, revoke_and_ack)
}

fn sign_with_fund_key_cb<SF>(
&self,
channel_lock: &mut ChannelLock<<K::Target as SignerProvider>::Signer>,
cb: &mut SF,
) where
SF: FnMut(&SecretKey),
{
self.sign_with_fund_key_callback(channel_lock, cb);
}

fn force_close_channel(
&self,
channel_id: &[u8; 32],
Expand All @@ -542,19 +544,6 @@ where
);
}

fn get_latest_holder_commitment_txn(
&self,
channel_lock: &ChannelLock<<K::Target as SignerProvider>::Signer>,
) -> Result<Vec<Transaction>, Error> {
self.get_latest_holder_commitment_txn(channel_lock)
.map_err(|e| {
Error::InvalidState(format!(
"Could not retrieve latest commitment transactions {:?}",
e
))
})
}

fn with_useable_channel_lock<C, RV>(
&self,
channel_id: &ChannelId,
Expand Down Expand Up @@ -584,6 +573,52 @@ where
}
}

impl<
ChannelSigner: WriteableEcdsaChannelSigner,
C: Deref,
T: Deref,
F: Deref,
L: Deref,
P: Deref,
> LNChainMonitor for ChainMonitor<ChannelSigner, C, T, F, L, P>
where
C::Target: lightning::chain::Filter,
T::Target: BroadcasterInterface,
F::Target: FeeEstimator,
L::Target: Logger,
P::Target: lightning::chain::chainmonitor::Persist<ChannelSigner>,
{
fn get_latest_holder_commitment_txn(
&self,
funding_txo: &lightning::chain::transaction::OutPoint,
) -> Result<Vec<Transaction>, Error> {
self.get_latest_holder_commitment_txn(funding_txo)
.map_err(|e| {
Error::InvalidParameters(format!("Could not get channel monitor: {:?}", e))
})
}

fn update_channel_funding_txo(
&self,
old_funding_txo: &lightning::chain::transaction::OutPoint,
new_funding_txo: &lightning::chain::transaction::OutPoint,
channel_value_satoshis: u64,
) -> Result<(), Error> {
match Watch::update_channel_funding_txo(
self,
*old_funding_txo,
*new_funding_txo,
channel_value_satoshis,
) {
lightning::chain::ChannelMonitorUpdateStatus::Completed => Ok(()),
s => Err(Error::InvalidState(format!(
"Unexpected channel monitor status {:?}",
s
))),
}
}
}

/// Generate a temporary channel id for a DLC channel based on the LN channel id, the update index of the
/// split transaction and the index of the DLC channel within the sub channel.
pub fn generate_temporary_channel_id(
Expand All @@ -597,3 +632,42 @@ pub fn generate_temporary_channel_id(
data.extend_from_slice(&channel_index.to_be_bytes());
bitcoin::hashes::sha256::Hash::hash(&data).into_inner()
}

/// Trait to be implemented by a signing component providing the ability to sign LN/DLC split
/// transactions. It is required that the signer's keys are identical to the ones used for the
/// original Lightning channel.
pub trait LnDlcChannelSigner {
/// Get the signature for the split transaction using the LN channel holder funding secret key.
fn get_holder_split_tx_signature(
&self,
secp: &secp256k1_zkp::Secp256k1<secp256k1_zkp::All>,
split_tx: &Transaction,
original_funding_redeemscript: &Script,
original_channel_value_satoshis: u64,
) -> Result<Signature, Error>;

/// Get an adaptor signature for the split transaction using the LN channel holder funding
/// secret key as the signing key, and the remote party publish public key as adaptor key.
fn get_holder_split_tx_adaptor_signature(
&self,
secp: &secp256k1_zkp::Secp256k1<secp256k1_zkp::All>,
split_tx: &Transaction,
original_channel_value_satoshis: u64,
original_funding_redeemscript: &Script,
other_publish_key: &PublicKey,
) -> Result<EcdsaAdaptorSignature, Error>;
}

/// Generates `Signer` that are able to sign split transaction for LN/DLC channels.
pub trait LnDlcSignerProvider<Signer: LnDlcChannelSigner> {
/// Derives the private key material backing a `Signer`.
///
/// To derive a new `Signer`, the same `channel_keys_id` and `channel_value_satoshis` parameter
/// that were provided to generate the LDK `ChannelSigner` shoud be passed, and the
/// implementation should derive the same key values.
fn derive_ln_dlc_channel_signer(
&self,
channel_value_satoshis: u64,
channel_keys_id: [u8; 32],
) -> Signer;
}
3 changes: 2 additions & 1 deletion dlc-manager/src/subchannel/ser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ impl_dlc_writeable!(SubChannel, {
(is_offer, writeable),
(own_fund_pk, writeable),
(counter_fund_pk, writeable),
(counter_party_secrets, writeable)
(counter_party_secrets, writeable),
(channel_keys_id, writeable)
});

impl_dlc_writeable_enum!(SubChannelState,
Expand Down
53 changes: 53 additions & 0 deletions dlc-manager/tests/custom_signer.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
use std::sync::{Arc, Mutex};

use bitcoin::{Script, Transaction, TxOut};
use dlc_manager::{
error::Error,
subchannel::{LnDlcChannelSigner, LnDlcSignerProvider},
};
use lightning::{
chain::keysinterface::{
ChannelSigner, EcdsaChannelSigner, EntropySource, ExtraSign, InMemorySigner, KeysManager,
Expand Down Expand Up @@ -252,6 +256,45 @@ impl Readable for CustomSigner {
}
}

impl LnDlcChannelSigner for CustomSigner {
fn get_holder_split_tx_signature(
&self,
secp: &Secp256k1<secp256k1_zkp::All>,
split_tx: &Transaction,
original_funding_redeemscript: &Script,
original_channel_value_satoshis: u64,
) -> Result<secp256k1_zkp::ecdsa::Signature, Error> {
dlc::util::get_raw_sig_for_tx_input(
secp,
&split_tx,
0,
original_funding_redeemscript,
original_channel_value_satoshis,
&self.in_memory_signer.lock().unwrap().funding_key,
)
.map_err(|e| e.into())
}

fn get_holder_split_tx_adaptor_signature(
&self,
secp: &Secp256k1<secp256k1_zkp::All>,
split_tx: &Transaction,
original_channel_value_satoshis: u64,
original_funding_redeemscript: &Script,
other_publish_key: &secp256k1_zkp::PublicKey,
) -> Result<secp256k1_zkp::EcdsaAdaptorSignature, Error> {
dlc::channel::get_tx_adaptor_signature(
secp,
&split_tx,
original_channel_value_satoshis,
original_funding_redeemscript,
&self.in_memory_signer.lock().unwrap().funding_key,
other_publish_key,
)
.map_err(|e| e.into())
}
}

impl WriteableEcdsaChannelSigner for CustomSigner {}

pub struct CustomKeysManager {
Expand Down Expand Up @@ -325,6 +368,16 @@ impl SignerProvider for CustomKeysManager {
}
}

impl LnDlcSignerProvider<CustomSigner> for CustomKeysManager {
fn derive_ln_dlc_channel_signer(
&self,
channel_value_satoshis: u64,
channel_keys_id: [u8; 32],
) -> CustomSigner {
self.derive_channel_signer(channel_value_satoshis, channel_keys_id)
}
}

impl EntropySource for CustomKeysManager {
fn get_secure_random_bytes(&self) -> [u8; 32] {
self.keys_manager.get_secure_random_bytes()
Expand Down
Loading

0 comments on commit f8716ae

Please sign in to comment.