mirror of
https://github.com/lightningdevkit/rust-lightning.git
synced 2025-02-25 07:17:40 +01:00
Lock outbound channels at 0conf if the peer indicates support for it
If our peer sets a minimum depth of 0, and we're set to trusting ourselves to not double-spend our own funding transactions, send a funding_locked message immediately after funding signed. Note that some special care has to be taken around the `channel_state` values - `ChannelFunded` no longer implies the funding transaction is confirmed on-chain. Thus, for example, the should-we-re-broadcast logic has to now accept `channel_state` values greater than `ChannelFunded` as indicating we may still need to re-broadcast our funding tranasction, unless `minimum_depth` is greater than 0. Further note that this starts writing `Channel` objects with a `MIN_SERIALIZATION_VERSION` of 2. Thus, LDK versions prior to 0.0.99 (July 2021) will now refuse to read serialized Channels/ChannelManagers.
This commit is contained in:
parent
168b3a51ae
commit
35cd39da15
4 changed files with 127 additions and 37 deletions
|
@ -710,6 +710,11 @@ pub(super) struct Channel<Signer: Sign> {
|
|||
// Our counterparty can offer us SCID aliases which they will map to this channel when routing
|
||||
// outbound payments. These can be used in invoice route hints to avoid explicitly revealing
|
||||
// the channel's funding UTXO.
|
||||
//
|
||||
// We also use this when sending our peer a channel_update that isn't to be broadcasted
|
||||
// publicly - allowing them to re-use their map of SCID -> channel for channel_update ->
|
||||
// associated channel mapping.
|
||||
//
|
||||
// We only bother storing the most recent SCID alias at any time, though our counterparty has
|
||||
// to store all of them.
|
||||
latest_inbound_scid_alias: Option<u64>,
|
||||
|
@ -1987,12 +1992,6 @@ impl<Signer: Sign> Channel<Signer> {
|
|||
if msg.minimum_depth > peer_limits.max_minimum_depth {
|
||||
return Err(ChannelError::Close(format!("We consider the minimum depth to be unreasonably large. Expected minimum: ({}). Actual: ({})", peer_limits.max_minimum_depth, msg.minimum_depth)));
|
||||
}
|
||||
if msg.minimum_depth == 0 {
|
||||
// Note that if this changes we should update the serialization minimum version to
|
||||
// indicate to older clients that they don't understand some features of the current
|
||||
// channel.
|
||||
return Err(ChannelError::Close("Minimum confirmation depth must be at least 1".to_owned()));
|
||||
}
|
||||
|
||||
if let Some(ty) = &msg.channel_type {
|
||||
if *ty != self.channel_type {
|
||||
|
@ -2029,7 +2028,12 @@ impl<Signer: Sign> Channel<Signer> {
|
|||
self.counterparty_selected_channel_reserve_satoshis = Some(msg.channel_reserve_satoshis);
|
||||
self.counterparty_htlc_minimum_msat = msg.htlc_minimum_msat;
|
||||
self.counterparty_max_accepted_htlcs = msg.max_accepted_htlcs;
|
||||
|
||||
if peer_limits.trust_own_funding_0conf {
|
||||
self.minimum_depth = Some(msg.minimum_depth);
|
||||
} else {
|
||||
self.minimum_depth = Some(cmp::max(1, msg.minimum_depth));
|
||||
}
|
||||
|
||||
let counterparty_pubkeys = ChannelPublicKeys {
|
||||
funding_pubkey: msg.funding_pubkey,
|
||||
|
@ -2169,7 +2173,7 @@ impl<Signer: Sign> Channel<Signer> {
|
|||
|
||||
/// Handles a funding_signed message from the remote end.
|
||||
/// If this call is successful, broadcast the funding transaction (and not before!)
|
||||
pub fn funding_signed<L: Deref>(&mut self, msg: &msgs::FundingSigned, best_block: BestBlock, logger: &L) -> Result<(ChannelMonitor<Signer>, Transaction), ChannelError> where L::Target: Logger {
|
||||
pub fn funding_signed<L: Deref>(&mut self, msg: &msgs::FundingSigned, best_block: BestBlock, logger: &L) -> Result<(ChannelMonitor<Signer>, Transaction, Option<msgs::FundingLocked>), ChannelError> where L::Target: Logger {
|
||||
if !self.is_outbound() {
|
||||
return Err(ChannelError::Close("Received funding_signed for an inbound channel?".to_owned()));
|
||||
}
|
||||
|
@ -2238,7 +2242,7 @@ impl<Signer: Sign> Channel<Signer> {
|
|||
|
||||
log_info!(logger, "Received funding_signed from peer for channel {}", log_bytes!(self.channel_id()));
|
||||
|
||||
Ok((channel_monitor, self.funding_transaction.as_ref().cloned().unwrap()))
|
||||
Ok((channel_monitor, self.funding_transaction.as_ref().cloned().unwrap(), self.check_get_funding_locked(0)))
|
||||
}
|
||||
|
||||
/// Handles a funding_locked message from our peer. If we've already sent our funding_locked
|
||||
|
@ -3540,12 +3544,13 @@ impl<Signer: Sign> Channel<Signer> {
|
|||
/// monitor update failure must *not* have been sent to the remote end, and must instead
|
||||
/// have been dropped. They will be regenerated when monitor_updating_restored is called.
|
||||
pub fn monitor_update_failed(&mut self, resend_raa: bool, resend_commitment: bool,
|
||||
mut pending_forwards: Vec<(PendingHTLCInfo, u64)>,
|
||||
resend_funding_locked: bool, mut pending_forwards: Vec<(PendingHTLCInfo, u64)>,
|
||||
mut pending_fails: Vec<(HTLCSource, PaymentHash, HTLCFailReason)>,
|
||||
mut pending_finalized_claimed_htlcs: Vec<HTLCSource>
|
||||
) {
|
||||
self.monitor_pending_revoke_and_ack |= resend_raa;
|
||||
self.monitor_pending_commitment_signed |= resend_commitment;
|
||||
self.monitor_pending_funding_locked |= resend_funding_locked;
|
||||
self.monitor_pending_forwards.append(&mut pending_forwards);
|
||||
self.monitor_pending_failures.append(&mut pending_fails);
|
||||
self.monitor_pending_finalized_fulfills.append(&mut pending_finalized_claimed_htlcs);
|
||||
|
@ -3559,9 +3564,18 @@ impl<Signer: Sign> Channel<Signer> {
|
|||
assert_eq!(self.channel_state & ChannelState::MonitorUpdateFailed as u32, ChannelState::MonitorUpdateFailed as u32);
|
||||
self.channel_state &= !(ChannelState::MonitorUpdateFailed as u32);
|
||||
|
||||
let funding_broadcastable = if self.channel_state & (ChannelState::FundingSent as u32) != 0 && self.is_outbound() {
|
||||
// If we're past (or at) the FundingSent stage on an outbound channel, try to
|
||||
// (re-)broadcast the funding transaction as we may have declined to broadcast it when we
|
||||
// first received the funding_signed.
|
||||
let mut funding_broadcastable =
|
||||
if self.is_outbound() && self.channel_state & !MULTI_STATE_FLAGS >= ChannelState::FundingSent as u32 {
|
||||
self.funding_transaction.take()
|
||||
} else { None };
|
||||
// That said, if the funding transaction is already confirmed (ie we're active with a
|
||||
// minimum_depth over 0) don't bother re-broadcasting the confirmed funding tx.
|
||||
if self.channel_state & !MULTI_STATE_FLAGS >= ChannelState::ChannelFunded as u32 && self.minimum_depth != Some(0) {
|
||||
funding_broadcastable = None;
|
||||
}
|
||||
|
||||
// We will never broadcast the funding transaction when we're in MonitorUpdateFailed (and
|
||||
// we assume the user never directly broadcasts the funding transaction and waits for us to
|
||||
|
@ -3570,7 +3584,8 @@ impl<Signer: Sign> Channel<Signer> {
|
|||
// the funding transaction confirmed before the monitor was persisted, or
|
||||
// * a 0-conf channel and intended to send the funding_locked before any broadcast at all.
|
||||
let funding_locked = if self.monitor_pending_funding_locked {
|
||||
assert!(!self.is_outbound(), "Funding transaction broadcast by the local client before it should have - LDK didn't do it!");
|
||||
assert!(!self.is_outbound() || self.minimum_depth == Some(0),
|
||||
"Funding transaction broadcast by the local client before it should have - LDK didn't do it!");
|
||||
self.monitor_pending_funding_locked = false;
|
||||
let next_per_commitment_point = self.holder_signer.get_per_commitment_point(self.cur_holder_commitment_transaction_number, &self.secp_ctx);
|
||||
Some(msgs::FundingLocked {
|
||||
|
@ -4552,6 +4567,11 @@ impl<Signer: Sign> Channel<Signer> {
|
|||
self.channel_state >= ChannelState::FundingSent as u32
|
||||
}
|
||||
|
||||
/// Returns true if our funding_locked has been sent
|
||||
pub fn is_our_funding_locked(&self) -> bool {
|
||||
(self.channel_state & ChannelState::OurFundingLocked as u32) != 0 || self.channel_state >= ChannelState::ChannelFunded as u32
|
||||
}
|
||||
|
||||
/// Returns true if our peer has either initiated or agreed to shut down the channel.
|
||||
pub fn received_shutdown(&self) -> bool {
|
||||
(self.channel_state & ChannelState::RemoteShutdownSent as u32) != 0
|
||||
|
@ -4582,7 +4602,7 @@ impl<Signer: Sign> Channel<Signer> {
|
|||
}
|
||||
|
||||
fn check_get_funding_locked(&mut self, height: u32) -> Option<msgs::FundingLocked> {
|
||||
if self.funding_tx_confirmation_height == 0 {
|
||||
if self.funding_tx_confirmation_height == 0 && self.minimum_depth != Some(0) {
|
||||
return None;
|
||||
}
|
||||
|
||||
|
@ -4759,9 +4779,9 @@ impl<Signer: Sign> Channel<Signer> {
|
|||
// close the channel and hope we can get the latest state on chain (because presumably
|
||||
// the funding transaction is at least still in the mempool of most nodes).
|
||||
//
|
||||
// Note that ideally we wouldn't force-close if we see *any* reorg on a 1-conf channel,
|
||||
// but not doing so may lead to the `ChannelManager::short_to_id` map being
|
||||
// inconsistent, so we currently have to.
|
||||
// Note that ideally we wouldn't force-close if we see *any* reorg on a 1-conf or
|
||||
// 0-conf channel, but not doing so may lead to the `ChannelManager::short_to_id` map
|
||||
// being inconsistent, so we currently have to.
|
||||
if funding_tx_confirmations == 0 && self.funding_tx_confirmed_in.is_some() {
|
||||
let err_reason = format!("Funding transaction was un-confirmed. Locked at {} confs, now have {} confs.",
|
||||
self.minimum_depth.unwrap(), funding_tx_confirmations);
|
||||
|
@ -5620,7 +5640,7 @@ impl<Signer: Sign> Channel<Signer> {
|
|||
}
|
||||
|
||||
const SERIALIZATION_VERSION: u8 = 2;
|
||||
const MIN_SERIALIZATION_VERSION: u8 = 1;
|
||||
const MIN_SERIALIZATION_VERSION: u8 = 2;
|
||||
|
||||
impl_writeable_tlv_based_enum!(InboundHTLCRemovalReason,;
|
||||
(0, FailRelay),
|
||||
|
@ -5685,12 +5705,10 @@ impl<Signer: Sign> Writeable for Channel<Signer> {
|
|||
|
||||
self.user_id.write(writer)?;
|
||||
|
||||
// Write out the old serialization for the config object. This is read by version-1
|
||||
// deserializers, but we will read the version in the TLV at the end instead.
|
||||
self.config.forwarding_fee_proportional_millionths.write(writer)?;
|
||||
self.config.cltv_expiry_delta.write(writer)?;
|
||||
self.config.announced_channel.write(writer)?;
|
||||
self.config.commit_upfront_shutdown_pubkey.write(writer)?;
|
||||
// Version 1 deserializers expected to read parts of the config object here. Version 2
|
||||
// deserializers (0.0.99) now read config through TLVs, and as we now require them for
|
||||
// `minimum_depth` we simply write dummy values here.
|
||||
writer.write_all(&[0; 8])?;
|
||||
|
||||
self.channel_id.write(writer)?;
|
||||
(self.channel_state | ChannelState::PeerDisconnected as u32).write(writer)?;
|
||||
|
|
|
@ -1286,7 +1286,7 @@ macro_rules! remove_channel {
|
|||
}
|
||||
|
||||
macro_rules! handle_monitor_err {
|
||||
($self: ident, $err: expr, $short_to_id: expr, $chan: expr, $action_type: path, $resend_raa: expr, $resend_commitment: expr, $failed_forwards: expr, $failed_fails: expr, $failed_finalized_fulfills: expr, $chan_id: expr) => {
|
||||
($self: ident, $err: expr, $short_to_id: expr, $chan: expr, $action_type: path, $resend_raa: expr, $resend_commitment: expr, $resend_funding_locked: expr, $failed_forwards: expr, $failed_fails: expr, $failed_finalized_fulfills: expr, $chan_id: expr) => {
|
||||
match $err {
|
||||
ChannelMonitorUpdateErr::PermanentFailure => {
|
||||
log_error!($self.logger, "Closing channel {} due to monitor update ChannelMonitorUpdateErr::PermanentFailure", log_bytes!($chan_id[..]));
|
||||
|
@ -1324,13 +1324,13 @@ macro_rules! handle_monitor_err {
|
|||
if !$resend_raa {
|
||||
debug_assert!($action_type == RAACommitmentOrder::CommitmentFirst || !$resend_commitment);
|
||||
}
|
||||
$chan.monitor_update_failed($resend_raa, $resend_commitment, $failed_forwards, $failed_fails, $failed_finalized_fulfills);
|
||||
$chan.monitor_update_failed($resend_raa, $resend_commitment, $resend_funding_locked, $failed_forwards, $failed_fails, $failed_finalized_fulfills);
|
||||
(Err(MsgHandleErrInternal::from_chan_no_close(ChannelError::Ignore("Failed to update ChannelMonitor".to_owned()), *$chan_id)), false)
|
||||
},
|
||||
}
|
||||
};
|
||||
($self: ident, $err: expr, $channel_state: expr, $entry: expr, $action_type: path, $resend_raa: expr, $resend_commitment: expr, $failed_forwards: expr, $failed_fails: expr, $failed_finalized_fulfills: expr) => { {
|
||||
let (res, drop) = handle_monitor_err!($self, $err, $channel_state.short_to_id, $entry.get_mut(), $action_type, $resend_raa, $resend_commitment, $failed_forwards, $failed_fails, $failed_finalized_fulfills, $entry.key());
|
||||
($self: ident, $err: expr, $channel_state: expr, $entry: expr, $action_type: path, $resend_raa: expr, $resend_commitment: expr, $resend_funding_locked: expr, $failed_forwards: expr, $failed_fails: expr, $failed_finalized_fulfills: expr) => { {
|
||||
let (res, drop) = handle_monitor_err!($self, $err, $channel_state.short_to_id, $entry.get_mut(), $action_type, $resend_raa, $resend_commitment, $resend_funding_locked, $failed_forwards, $failed_fails, $failed_finalized_fulfills, $entry.key());
|
||||
if drop {
|
||||
$entry.remove_entry();
|
||||
}
|
||||
|
@ -1338,16 +1338,19 @@ macro_rules! handle_monitor_err {
|
|||
} };
|
||||
($self: ident, $err: expr, $channel_state: expr, $entry: expr, $action_type: path, $chan_id: expr, COMMITMENT_UPDATE_ONLY) => { {
|
||||
debug_assert!($action_type == RAACommitmentOrder::CommitmentFirst);
|
||||
handle_monitor_err!($self, $err, $channel_state, $entry, $action_type, false, true, Vec::new(), Vec::new(), Vec::new(), $chan_id)
|
||||
handle_monitor_err!($self, $err, $channel_state, $entry, $action_type, false, true, false, Vec::new(), Vec::new(), Vec::new(), $chan_id)
|
||||
} };
|
||||
($self: ident, $err: expr, $channel_state: expr, $entry: expr, $action_type: path, $chan_id: expr, NO_UPDATE) => {
|
||||
handle_monitor_err!($self, $err, $channel_state, $entry, $action_type, false, false, Vec::new(), Vec::new(), Vec::new(), $chan_id)
|
||||
handle_monitor_err!($self, $err, $channel_state, $entry, $action_type, false, false, false, Vec::new(), Vec::new(), Vec::new(), $chan_id)
|
||||
};
|
||||
($self: ident, $err: expr, $channel_state: expr, $entry: expr, $action_type: path, $resend_funding_locked: expr, OPTIONALLY_RESEND_FUNDING_LOCKED) => {
|
||||
handle_monitor_err!($self, $err, $channel_state, $entry, $action_type, false, false, $resend_funding_locked, Vec::new(), Vec::new(), Vec::new())
|
||||
};
|
||||
($self: ident, $err: expr, $channel_state: expr, $entry: expr, $action_type: path, $resend_raa: expr, $resend_commitment: expr) => {
|
||||
handle_monitor_err!($self, $err, $channel_state, $entry, $action_type, $resend_raa, $resend_commitment, Vec::new(), Vec::new(), Vec::new())
|
||||
handle_monitor_err!($self, $err, $channel_state, $entry, $action_type, $resend_raa, $resend_commitment, false, Vec::new(), Vec::new(), Vec::new())
|
||||
};
|
||||
($self: ident, $err: expr, $channel_state: expr, $entry: expr, $action_type: path, $resend_raa: expr, $resend_commitment: expr, $failed_forwards: expr, $failed_fails: expr) => {
|
||||
handle_monitor_err!($self, $err, $channel_state, $entry, $action_type, $resend_raa, $resend_commitment, $failed_forwards, $failed_fails, Vec::new())
|
||||
handle_monitor_err!($self, $err, $channel_state, $entry, $action_type, $resend_raa, $resend_commitment, false, $failed_forwards, $failed_fails, Vec::new())
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -4268,7 +4271,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
|
|||
// hasn't persisted to disk yet - we can't lose money on a transaction that we haven't
|
||||
// accepted payment from yet. We do, however, need to wait to send our funding_locked
|
||||
// until we have persisted our monitor.
|
||||
chan.monitor_update_failed(false, false, Vec::new(), Vec::new(), Vec::new());
|
||||
chan.monitor_update_failed(false, false, false, Vec::new(), Vec::new(), Vec::new());
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -4299,12 +4302,12 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
|
|||
if chan.get().get_counterparty_node_id() != *counterparty_node_id {
|
||||
return Err(MsgHandleErrInternal::send_err_msg_no_close("Got a message for a channel from the wrong node!".to_owned(), msg.channel_id));
|
||||
}
|
||||
let (monitor, funding_tx) = match chan.get_mut().funding_signed(&msg, best_block, &self.logger) {
|
||||
let (monitor, funding_tx, funding_locked) = match chan.get_mut().funding_signed(&msg, best_block, &self.logger) {
|
||||
Ok(update) => update,
|
||||
Err(e) => try_chan_entry!(self, Err(e), channel_state, chan),
|
||||
};
|
||||
if let Err(e) = self.chain_monitor.watch_channel(chan.get().get_funding_txo().unwrap(), monitor) {
|
||||
let mut res = handle_monitor_err!(self, e, channel_state, chan, RAACommitmentOrder::RevokeAndACKFirst, false, false);
|
||||
let mut res = handle_monitor_err!(self, e, channel_state, chan, RAACommitmentOrder::RevokeAndACKFirst, funding_locked.is_some(), OPTIONALLY_RESEND_FUNDING_LOCKED);
|
||||
if let Err(MsgHandleErrInternal { ref mut shutdown_finish, .. }) = res {
|
||||
// We weren't able to watch the channel to begin with, so no updates should be made on
|
||||
// it. Previously, full_stack_target found an (unreachable) panic when the
|
||||
|
@ -4315,6 +4318,9 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
|
|||
}
|
||||
return res
|
||||
}
|
||||
if let Some(msg) = funding_locked {
|
||||
send_funding_locked!(channel_state.short_to_id, channel_state.pending_msg_events, chan.get(), msg);
|
||||
}
|
||||
funding_tx
|
||||
},
|
||||
hash_map::Entry::Vacant(_) => return Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel".to_owned(), msg.channel_id))
|
||||
|
@ -4665,7 +4671,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
|
|||
} else {
|
||||
if let Err(e) = handle_monitor_err!(self, e, channel_state, chan,
|
||||
RAACommitmentOrder::CommitmentFirst, false,
|
||||
raa_updates.commitment_update.is_some(),
|
||||
raa_updates.commitment_update.is_some(), false,
|
||||
raa_updates.accepted_htlcs, raa_updates.failed_htlcs,
|
||||
raa_updates.finalized_claimed_htlcs) {
|
||||
break Err(e);
|
||||
|
@ -5520,6 +5526,19 @@ where
|
|||
}
|
||||
}
|
||||
}
|
||||
if channel.is_our_funding_locked() {
|
||||
if let Some(real_scid) = channel.get_short_channel_id() {
|
||||
// If we sent a 0conf funding_locked, and now have an SCID, we add it
|
||||
// to the short_to_id map here. Note that we check whether we can relay
|
||||
// using the real SCID at relay-time (i.e. enforce option_scid_alias
|
||||
// then), and if the funding tx is ever un-confirmed we force-close the
|
||||
// channel, ensuring short_to_id is always consistent.
|
||||
let scid_insert = short_to_id.insert(real_scid, channel.channel_id());
|
||||
assert!(scid_insert.is_none() || scid_insert.unwrap() == channel.channel_id(),
|
||||
"SCIDs should never collide - ensure you weren't behind by a full {} blocks when creating channels",
|
||||
fake_scid::MAX_SCID_BLOCKS_FROM_NOW);
|
||||
}
|
||||
}
|
||||
} else if let Err(reason) = res {
|
||||
update_maps_on_chan_removal!(self, short_to_id, channel);
|
||||
// It looks like our counterparty went on-chain or funding transaction was
|
||||
|
|
|
@ -564,3 +564,37 @@ fn test_scid_alias_returned() {
|
|||
PaymentFailedConditions::new().blamed_scid(last_hop[0].inbound_scid_alias.unwrap())
|
||||
.blamed_chan_closed(false).expected_htlc_error_data(0x1000|12, &err_data));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_simple_0conf_channel() {
|
||||
// If our peer tells us they will accept our channel with 0 confs, and we funded the channel,
|
||||
// we should trust the funding won't be double-spent (assuming `trust_own_funding_0conf` is
|
||||
// set)!
|
||||
|
||||
let chanmon_cfgs = create_chanmon_cfgs(2);
|
||||
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
|
||||
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
|
||||
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
|
||||
|
||||
nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100000, 10001, 42, None).unwrap();
|
||||
let open_channel = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id());
|
||||
|
||||
nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), InitFeatures::known(), &open_channel);
|
||||
let mut accept_channel = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id());
|
||||
accept_channel.minimum_depth = 0;
|
||||
nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), InitFeatures::known(), &accept_channel);
|
||||
|
||||
let (temporary_channel_id, tx, _) = create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 100000, 42);
|
||||
nodes[0].node.funding_transaction_generated(&temporary_channel_id, &nodes[1].node.get_our_node_id(), tx.clone()).unwrap();
|
||||
let funding_created = get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id());
|
||||
|
||||
nodes[1].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &funding_created);
|
||||
check_added_monitors!(nodes[1], 1);
|
||||
let funding_signed = get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, nodes[0].node.get_our_node_id());
|
||||
|
||||
nodes[0].node.handle_funding_signed(&nodes[1].node.get_our_node_id(), &funding_signed);
|
||||
check_added_monitors!(nodes[0], 1);
|
||||
|
||||
let as_funding_locked = get_event_msg!(nodes[0], MessageSendEvent::SendFundingLocked, nodes[1].node.get_our_node_id());
|
||||
nodes[1].node.handle_funding_locked(&nodes[0].node.get_our_node_id(), &as_funding_locked);
|
||||
}
|
||||
|
|
|
@ -159,6 +159,24 @@ pub struct ChannelHandshakeLimits {
|
|||
///
|
||||
/// Default value: 144, or roughly one day and only applies to outbound channels.
|
||||
pub max_minimum_depth: u32,
|
||||
/// Whether we implicitly trust funding transactions generated by us for our own outbound
|
||||
/// channels to not be double-spent.
|
||||
///
|
||||
/// If this is set, we assume that our own funding transactions are *never* double-spent, and
|
||||
/// thus we can trust them without any confirmations. This is generally a reasonable
|
||||
/// assumption, given we're the only ones who could ever double-spend it (assuming we have sole
|
||||
/// control of the signing keys).
|
||||
///
|
||||
/// You may wish to un-set this if you allow the user to (or do in an automated fashion)
|
||||
/// double-spend the funding transaction to RBF with an alternative channel open.
|
||||
///
|
||||
/// This only applies if our counterparty set their confirmations-required value to 0, and we
|
||||
/// always trust our own funding transaction at 1 confirmation irrespective of this value.
|
||||
/// Thus, this effectively acts as a `min_minimum_depth`, with the only possible values being
|
||||
/// `true` (0) and `false` (1).
|
||||
///
|
||||
/// Default value: true
|
||||
pub trust_own_funding_0conf: bool,
|
||||
/// Set to force an incoming channel to match our announced channel preference in
|
||||
/// [`ChannelConfig::announced_channel`].
|
||||
///
|
||||
|
@ -187,6 +205,7 @@ impl Default for ChannelHandshakeLimits {
|
|||
min_max_htlc_value_in_flight_msat: 0,
|
||||
max_channel_reserve_satoshis: <u64>::max_value(),
|
||||
min_max_accepted_htlcs: 0,
|
||||
trust_own_funding_0conf: true,
|
||||
max_minimum_depth: 144,
|
||||
force_announced_channel_preference: true,
|
||||
their_to_self_delay: MAX_LOCAL_BREAKDOWN_TIMEOUT,
|
||||
|
|
Loading…
Add table
Reference in a new issue