Skip to content

Commit

Permalink
fixup! Claim DLC channel settle transactions
Browse files Browse the repository at this point in the history
  • Loading branch information
luckysori committed Mar 13, 2024
1 parent 8e4c49b commit 30958df
Show file tree
Hide file tree
Showing 10 changed files with 262 additions and 135 deletions.
43 changes: 43 additions & 0 deletions dlc-manager/src/chain_monitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,12 @@ pub(crate) enum TxType {
BufferTx,
CollaborativeClose,
SplitTx,
// TODO: Add `is_offer` here.
SettleTx,
Cet,
SettleTx2 {
is_offer: bool,
},
}

impl_dlc_writeable_enum!(TxType,;
Expand All @@ -55,6 +59,9 @@ impl_dlc_writeable_enum!(TxType,;
(own_adaptor_signature, {cb_writeable, write_ecdsa_adaptor_signature, read_ecdsa_adaptor_signature}),
(is_offer, writeable),
(revoked_tx_type, writeable)
}),
(6, SettleTx2, {
(is_offer, writeable)
});;
(1, BufferTx), (2, CollaborativeClose), (3, SplitTx), (4, SettleTx), (5, Cet)
);
Expand Down Expand Up @@ -180,6 +187,42 @@ impl ChainMonitor {
}
}

pub(crate) fn did_we_offer_last_channel_settlement(
&self,
channel_id: &[u8; 32],
) -> Option<bool> {
let mut watched_txs = self.watched_tx.iter();

watched_txs.find_map(|(_, state)| match state {
WatchState::Registered {
channel_info:
ChannelInfo {
channel_id: cid,
tx_type:
TxType::Revoked {
revoked_tx_type: RevokedTxType::Buffer,
is_offer,
..
},
},
}
| WatchState::Confirmed {
channel_info:
ChannelInfo {
channel_id: cid,
tx_type:
TxType::Revoked {
revoked_tx_type: RevokedTxType::Buffer,
is_offer,
..
},
},
..
} if channel_id == cid => Some(*is_offer),
_ => None,
})
}

/// All the currently watched transactions which have been confirmed.
pub(crate) fn confirmed_txs(&self) -> Vec<(Transaction, ChannelInfo)> {
(self.watched_tx.values())
Expand Down
30 changes: 30 additions & 0 deletions dlc-manager/src/channel/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ pub enum Channel {
/// has broadcast a buffer transaction and is waiting to finalize the
/// closing of the channel by broadcasting a CET.
Closing(ClosingChannel),
/// A [`Channel`] is in `SettledClosing` state when the local party
/// has broadcast a settle transaction and is waiting to finalize the
/// closing of the channel by claiming their output.
SettledClosing(SettledClosingChannel),
/// A [`Channel`] is in `Closed` state when it was force closed by
/// the local party.
Closed(ClosedChannel),
Expand Down Expand Up @@ -64,6 +68,7 @@ impl std::fmt::Debug for Channel {
Channel::FailedAccept(_) => "failed accept",
Channel::FailedSign(_) => "failed sign",
Channel::Closing(_) => "closing",
Channel::SettledClosing(_) => "settled closing",
Channel::Closed(_) => "closed",
Channel::CounterClosed(_) => "counter closed",
Channel::ClosedPunished(_) => "closed punished",
Expand All @@ -84,6 +89,7 @@ impl Channel {
Channel::FailedAccept(f) => f.counter_party,
Channel::FailedSign(f) => f.counter_party,
Channel::Closing(c) => c.counter_party,
Channel::SettledClosing(c) => c.counter_party,
Channel::Closed(c) | Channel::CounterClosed(c) | Channel::CollaborativelyClosed(c) => {
c.counter_party
}
Expand All @@ -101,6 +107,7 @@ impl Channel {
Channel::FailedAccept(f) => f.reference_id,
Channel::FailedSign(f) => f.reference_id,
Channel::Closing(c) => c.reference_id,
Channel::SettledClosing(c) => c.reference_id,
Channel::Closed(c) | Channel::CounterClosed(c) | Channel::CollaborativelyClosed(c) => {
c.reference_id
}
Expand Down Expand Up @@ -167,6 +174,28 @@ pub struct ClosingChannel {
pub reference_id: Option<ReferenceId>,
}

#[derive(Clone)]
/// A channel is closing when its buffer transaction was broadcast or detected on chain.
pub struct SettledClosingChannel {
/// The [`secp256k1_zkp::PublicKey`] of the counter party.
pub counter_party: PublicKey,
/// The temporary [`DlcChannelId`] of the channel.
pub temporary_channel_id: DlcChannelId,
/// The [`DlcChannelId`] for the channel.
pub channel_id: DlcChannelId,
/// The previous state the channel was before being closed, if that state was the `Signed` one,
/// otherwise is `None`.
pub rollback_state: Option<SignedChannel>,
/// The settle transaction that was broadcast.
pub settle_transaction: Transaction,
/// The claim transaction that was broadcast.
pub claim_transaction: Transaction,
/// Whether the local party initiated the closing of the channel.
pub is_closer: bool,
/// The reference id set by the api user.
pub reference_id: Option<ReferenceId>,
}

#[derive(Clone)]
/// A channel is closed when its buffer transaction has been spent.
pub struct ClosedChannel {
Expand Down Expand Up @@ -223,6 +252,7 @@ impl Channel {
Channel::FailedAccept(f) => f.temporary_channel_id,
Channel::FailedSign(f) => f.channel_id,
Channel::Closing(c) => c.channel_id,
Channel::SettledClosing(c) => c.channel_id,
Channel::Closed(c) | Channel::CounterClosed(c) | Channel::CollaborativelyClosed(c) => {
c.channel_id
}
Expand Down
14 changes: 12 additions & 2 deletions dlc-manager/src/channel/ser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use super::accepted_channel::AcceptedChannel;
use super::offered_channel::OfferedChannel;
use super::party_points::PartyBasePoints;
use super::signed_channel::{SignedChannel, SignedChannelState};
use super::{ClosedChannel, ClosedPunishedChannel, ClosingChannel, FailedAccept, FailedSign};
use super::{ClosedChannel, ClosedPunishedChannel, ClosingChannel, FailedAccept, FailedSign, SettledClosingChannel};

use dlc_messages::ser_impls::{
read_ecdsa_adaptor_signature, read_string, write_ecdsa_adaptor_signature, write_string,
Expand Down Expand Up @@ -65,7 +65,7 @@ impl_dlc_writeable_enum!(
(10, RenewFinalized, {(contract_id, writeable), (prev_offer_per_update_point, writeable), (buffer_transaction, writeable), (buffer_script_pubkey, writeable), (offer_buffer_adaptor_signature, {cb_writeable, write_ecdsa_adaptor_signature, read_ecdsa_adaptor_signature}), (accept_buffer_adaptor_signature, {cb_writeable, write_ecdsa_adaptor_signature, read_ecdsa_adaptor_signature}), (timeout, writeable), (own_payout, writeable), (total_collateral, writeable)}),
(9, Closing, {(buffer_transaction, writeable), (contract_id, writeable), (is_initiator, writeable)}),
(11, CollaborativeCloseOffered, { (counter_payout, writeable), (offer_signature, writeable), (close_tx, writeable), (timeout, writeable), (is_offer, writeable) }),
(12, SettledClosing, {(settle_transaction, writeable), (contract_id, writeable), (is_initiator, writeable)})
(12, SettledClosing, {(settle_transaction, writeable), (is_offer, writeable), (is_initiator, writeable)})
;;
);

Expand All @@ -82,5 +82,15 @@ impl_dlc_writeable!(ClosingChannel, {
(is_closer, writeable),
(reference_id, option)
});
impl_dlc_writeable!(SettledClosingChannel, {
(channel_id, writeable),
(counter_party, writeable),
(temporary_channel_id, writeable),
(rollback_state, option),
(settle_transaction, writeable),
(claim_transaction, writeable),
(is_closer, writeable),
(reference_id, option)
});
impl_dlc_writeable!(ClosedChannel, {(channel_id, writeable), (counter_party, writeable), (temporary_channel_id, writeable), (reference_id, option), (closing_txid, writeable)});
impl_dlc_writeable!(ClosedPunishedChannel, {(channel_id, writeable), (counter_party, writeable), (temporary_channel_id, writeable), (punish_txid, writeable), (reference_id, option)});
11 changes: 5 additions & 6 deletions dlc-manager/src/channel/signed_channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -297,15 +297,14 @@ typed_enum!(
/// Whether the local party initiated the closing of the channel.
is_initiator: bool,
},
/// A [`SignedChannel`] is in `SettledClosing` state when the local party
/// has broadcast a settle transaction and is waiting to finalize the
/// closing of a the channel by claiming one of its outputs.
/// A [`SignedChannel`] is in `SettledClosing` state when a settle transaction has been
/// broadcast, and we are waiting to finalize the closing of the channel by claiming one of
/// its outputs.
SettledClosing {
/// The settle transaction that was broadcast.
settle_transaction: Transaction,
/// The [`crate::ContractId`] of the contract that was used to close
/// the channel.
contract_id: ContractId,
/// Indicates whether the local party originally offered to settle the channel or not.
is_offer: bool,
/// Whether the local party initiated the closing of the channel.
is_initiator: bool,
},
Expand Down
83 changes: 23 additions & 60 deletions dlc-manager/src/channel_updater.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::{chain_monitor::{ChainMonitor, ChannelInfo, TxType}, channel::{
offered_channel::OfferedChannel,
party_points::PartyBasePoints,
signed_channel::{SignedChannel, SignedChannelState},
Channel, ClosedChannel,
Channel, ClosedChannel, SettledClosingChannel,
}, contract::{
accepted_contract::AcceptedContract, contract_info::ContractInfo,
contract_input::ContractInput, offered_contract::OfferedContract,
Expand Down Expand Up @@ -2717,6 +2717,7 @@ pub(crate) fn initiate_unilateral_close_settled_channel<S: Deref>(
signed_channel: &mut SignedChannel,
signer: &S,
sub_channel: Option<(SubChannel, &ClosingSubChannel)>,
is_settle_offer: bool,
is_initiator: bool,
reference_id: Option<ReferenceId>
) -> Result<(), Error>
Expand Down Expand Up @@ -2820,15 +2821,11 @@ where
)?;
}

let contract_id = signed_channel.get_contract_id().ok_or_else(|| {
Error::InvalidState(
"Expected to be in a state with an associated contract id but was not.".to_string(),
)
})?;


signed_channel.state = SignedChannelState::SettledClosing {
settle_transaction: settle_tx,
contract_id,
is_offer: is_settle_offer,
is_initiator,
};

Expand All @@ -2841,10 +2838,10 @@ where
pub fn finalize_unilateral_close_settled_channel<S: Deref>(
secp: &Secp256k1<All>,
signed_channel: &SignedChannel,
confirmed_contract: &SignedContract,
destination_address: &Address,
fee_rate_per_vb: u64,
signer: &S,
is_offer: bool,
is_initiator: bool,
) -> Result<(Transaction, Channel), Error>
where
Expand All @@ -2853,61 +2850,28 @@ where
let settle_transaction =
get_signed_channel_state!(signed_channel, SettledClosing, settle_transaction)?;

let is_offer = confirmed_contract
.accepted_contract
.offered_contract
.is_offer_party;



let (offer_points, accept_points, offer_per_update_point, accept_per_update_point) = if is_offer
{
(
&signed_channel.own_points,
&signed_channel.counter_points,
&signed_channel.own_per_update_point,
&signed_channel.counter_per_update_point,
)
} else {
(
&signed_channel.counter_points,
&signed_channel.own_points,
&signed_channel.counter_per_update_point,
&signed_channel.own_per_update_point,
)
};

let offer_revoke_params = offer_points.get_revokable_params(
let own_revoke_params = signed_channel.own_points.get_revokable_params(
secp,
&accept_points.revocation_basepoint,
offer_per_update_point,
&signed_channel.counter_points.revocation_basepoint,
&signed_channel.own_per_update_point,
);

let accept_revoke_params = accept_points.get_revokable_params(
let counter_revoke_params = signed_channel.counter_points.get_revokable_params(
secp,
&offer_points.revocation_basepoint,
accept_per_update_point,
&signed_channel.own_points.revocation_basepoint,
&signed_channel.counter_per_update_point,
);

let (own_per_update_point, own_basepoint) = if is_offer {
(
&offer_per_update_point,
&offer_points.own_basepoint,
)
} else {
(
&accept_per_update_point,
&accept_points.own_basepoint,
)
};
let own_basepoint = signed_channel.own_points.own_basepoint;
let own_per_update_point = signed_channel.own_per_update_point;

let base_secret = signer.get_secret_key_for_pubkey(own_basepoint)?;
let own_sk = derive_private_key(secp, own_per_update_point, &base_secret);
let base_secret = signer.get_secret_key_for_pubkey(&own_basepoint)?;
let own_sk = derive_private_key(secp, &own_per_update_point, &base_secret);

let claim_tx = dlc::channel::create_and_sign_claim_settle_transaction(
secp,
&offer_revoke_params,
&accept_revoke_params,
&own_revoke_params,
&counter_revoke_params,
&own_sk,
settle_transaction,
destination_address,
Expand All @@ -2917,19 +2881,18 @@ where
is_offer,
)?;

let closed_channel = ClosedChannel {
let closing_channel = SettledClosingChannel {
counter_party: signed_channel.counter_party,
temporary_channel_id: signed_channel.temporary_channel_id,
channel_id: signed_channel.channel_id,
rollback_state: Some(signed_channel.clone()),
settle_transaction: settle_transaction.clone(),
claim_transaction: claim_tx.clone(),
is_closer: is_initiator,
reference_id: signed_channel.reference_id,
closing_txid: claim_tx.txid()
};

let channel = if is_initiator {
Channel::Closed(closed_channel)
} else {
Channel::CounterClosed(closed_channel)
};
let channel = Channel::SettledClosing(closing_channel);

Ok((claim_tx, channel))
}
Expand Down
4 changes: 3 additions & 1 deletion dlc-manager/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ use bitcoin::{Address, Block, OutPoint, Script, Transaction, TxOut, Txid};
use chain_monitor::ChainMonitor;
use channel::offered_channel::OfferedChannel;
use channel::signed_channel::{SignedChannel, SignedChannelStateType};
use channel::Channel;
use channel::{Channel, SettledClosingChannel};
use contract::PreClosedContract;
use contract::{offered_contract::OfferedContract, signed_contract::SignedContract, Contract};
use dlc_messages::oracle_msgs::{OracleAnnouncement, OracleAttestation};
Expand Down Expand Up @@ -182,6 +182,8 @@ pub trait Storage {
) -> Result<Vec<SignedChannel>, Error>;
/// Returns the set of channels in offer state.
fn get_offered_channels(&self) -> Result<Vec<OfferedChannel>, Error>;
/// Returns the set of channels in settled closing state.
fn get_settled_closing_channels(&self) -> Result<Vec<SettledClosingChannel>, Error>;
/// Writes the [`ChainMonitor`] data to the store.
fn persist_chain_monitor(&self, monitor: &ChainMonitor) -> Result<(), Error>;
/// Returns the latest [`ChainMonitor`] in the store if any.
Expand Down
Loading

0 comments on commit 30958df

Please sign in to comment.