const CHECK_CLTV_EXPIRY_SANITY_2: u32 = CLTV_EXPIRY_DELTA as u32 - LATENCY_GRACE_PERIOD_BLOCKS - 2*CLTV_CLAIM_BUFFER;
/// Details of a channel, as returned by ChannelManager::list_channels and ChannelManager::list_usable_channels
+#[derive(Clone)]
pub struct ChannelDetails {
/// The channel's ID (prior to funding transaction generation, this is a random 32 bytes,
/// thereafter this is the txid of the funding transaction xor the funding transaction output).
/// If a payment fails to send, it can be in one of several states. This enum is returned as the
/// Err() type describing which state the payment is in, see the description of individual enum
/// states for more.
-#[derive(Debug)]
+#[derive(Clone, Debug)]
pub enum PaymentSendFailure {
/// A parameter which was passed to send_payment was invalid, preventing us from attempting to
/// send the payment at all. No channel state has been changed or messages sent to peers, and
}
}
- /// Force closes a channel, immediately broadcasting the latest local commitment transaction to
- /// the chain and rejecting new HTLCs on the given channel.
- pub fn force_close_channel(&self, channel_id: &[u8; 32]) {
- let _consistency_lock = self.total_consistency_lock.read().unwrap();
-
+ fn force_close_channel_with_peer(&self, channel_id: &[u8; 32], peer_node_id: Option<&PublicKey>) -> Result<(), APIError> {
let mut chan = {
let mut channel_state_lock = self.channel_state.lock().unwrap();
let channel_state = &mut *channel_state_lock;
- if let Some(chan) = channel_state.by_id.remove(channel_id) {
- if let Some(short_id) = chan.get_short_channel_id() {
+ if let hash_map::Entry::Occupied(chan) = channel_state.by_id.entry(channel_id.clone()) {
+ if let Some(node_id) = peer_node_id {
+ if chan.get().get_counterparty_node_id() != *node_id {
+ // Error or Ok here doesn't matter - the result is only exposed publicly
+ // when peer_node_id is None anyway.
+ return Ok(());
+ }
+ }
+ if let Some(short_id) = chan.get().get_short_channel_id() {
channel_state.short_to_id.remove(&short_id);
}
- chan
+ chan.remove_entry().1
} else {
- return;
+ return Err(APIError::ChannelUnavailable{err: "No such channel".to_owned()});
}
};
log_trace!(self.logger, "Force-closing channel {}", log_bytes!(channel_id[..]));
msg: update
});
}
+
+ Ok(())
+ }
+
+ /// Force closes a channel, immediately broadcasting the latest local commitment transaction to
+ /// the chain and rejecting new HTLCs on the given channel. Fails if channel_id is unknown to the manager.
+ pub fn force_close_channel(&self, channel_id: &[u8; 32]) -> Result<(), APIError> {
+ let _consistency_lock = self.total_consistency_lock.read().unwrap();
+ self.force_close_channel_with_peer(channel_id, None)
}
/// Force close all channels, immediately broadcasting the latest local commitment transaction
/// for each to the chain and rejecting new HTLCs on each.
pub fn force_close_all_channels(&self) {
for chan in self.list_channels() {
- self.force_close_channel(&chan.channel_id);
+ let _ = self.force_close_channel(&chan.channel_id);
}
}
&events::MessageSendEvent::BroadcastChannelUpdate { .. } => true,
&events::MessageSendEvent::HandleError { ref node_id, .. } => node_id != counterparty_node_id,
&events::MessageSendEvent::PaymentFailureNetworkUpdate { .. } => true,
+ &events::MessageSendEvent::SendChannelRangeQuery { .. } => false,
+ &events::MessageSendEvent::SendShortIdsQuery { .. } => false,
}
});
}
if msg.channel_id == [0; 32] {
for chan in self.list_channels() {
if chan.remote_network_id == *counterparty_node_id {
- self.force_close_channel(&chan.channel_id);
+ // Untrusted messages from peer, we throw away the error if id points to a non-existent channel
+ let _ = self.force_close_channel_with_peer(&chan.channel_id, Some(counterparty_node_id));
}
}
} else {
- self.force_close_channel(&msg.channel_id);
+ // Untrusted messages from peer, we throw away the error if id points to a non-existent channel
+ let _ = self.force_close_channel_with_peer(&msg.channel_id, Some(counterparty_node_id));
}
}
}
}
}
-impl<ChanSigner: ChannelKeys + Writeable, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> Writeable for ChannelManager<ChanSigner, M, T, K, F, L>
+impl<ChanSigner: ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> Writeable for ChannelManager<ChanSigner, M, T, K, F, L>
where M::Target: chain::Watch<Keys=ChanSigner>,
T::Target: BroadcasterInterface,
K::Target: KeysInterface<ChanKeySigner = ChanSigner>,
L::Target: Logger,
{
/// The keys provider which will give us relevant keys. Some keys will be loaded during
- /// deserialization.
+ /// deserialization and KeysInterface::read_chan_signer will be used to read per-Channel
+ /// signing data.
pub keys_manager: K,
/// The fee_estimator for use in the ChannelManager in the future.
// Implement ReadableArgs for an Arc'd ChannelManager to make it a bit easier to work with the
// SipmleArcChannelManager type:
-impl<'a, ChanSigner: ChannelKeys + Readable, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
+impl<'a, ChanSigner: ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
ReadableArgs<ChannelManagerReadArgs<'a, ChanSigner, M, T, K, F, L>> for (BlockHash, Arc<ChannelManager<ChanSigner, M, T, K, F, L>>)
where M::Target: chain::Watch<Keys=ChanSigner>,
T::Target: BroadcasterInterface,
}
}
-impl<'a, ChanSigner: ChannelKeys + Readable, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
+impl<'a, ChanSigner: ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
ReadableArgs<ChannelManagerReadArgs<'a, ChanSigner, M, T, K, F, L>> for (BlockHash, ChannelManager<ChanSigner, M, T, K, F, L>)
where M::Target: chain::Watch<Keys=ChanSigner>,
T::Target: BroadcasterInterface,
let mut by_id = HashMap::with_capacity(cmp::min(channel_count as usize, 128));
let mut short_to_id = HashMap::with_capacity(cmp::min(channel_count as usize, 128));
for _ in 0..channel_count {
- let mut channel: Channel<ChanSigner> = Readable::read(reader)?;
+ let mut channel: Channel<ChanSigner> = Channel::read(reader, &args.keys_manager)?;
if channel.last_block_connected != Default::default() && channel.last_block_connected != last_block_hash {
return Err(DecodeError::InvalidValue);
}