},
}),
},
+ ChannelError::CloseDelayBroadcast { msg, .. } => HandleError {
+ err: msg,
+ action: Some(msgs::ErrorAction::SendErrorMessage {
+ msg: msgs::ErrorMessage {
+ channel_id,
+ data: msg.to_string()
+ },
+ }),
+ },
},
shutdown_finish: None,
}
}
break Err(MsgHandleErrInternal::from_finish_shutdown(msg, channel_id, chan.force_shutdown(), $self.get_channel_update(&chan).ok()))
},
+ Err(ChannelError::CloseDelayBroadcast { .. }) => { panic!("Wait is only generated on receipt of channel_reestablish, which is handled by try_chan_entry, we don't bother to support it here"); }
}
}
}
}
return Err(MsgHandleErrInternal::from_finish_shutdown(msg, channel_id, chan.force_shutdown(), $self.get_channel_update(&chan).ok()))
},
+ Err(ChannelError::CloseDelayBroadcast { msg, update }) => {
+ log_error!($self, "Channel {} need to be shutdown but closing transactions not broadcast due to {}", log_bytes!($entry.key()[..]), msg);
+ let (channel_id, mut chan) = $entry.remove_entry();
+ if let Some(short_id) = chan.get_short_channel_id() {
+ $channel_state.short_to_id.remove(&short_id);
+ }
+ if let Some(update) = update {
+ if let Err(e) = $self.monitor.add_update_monitor(update.get_funding_txo().unwrap(), update) {
+ match e {
+ // Upstream channel is dead, but we want at least to fail backward HTLCs to save
+ // downstream channels. In case of PermanentFailure, we are not going to be able
+ // to claim back to_remote output on remote commitment transaction. Doesn't
+ // make a difference here, we are concern about HTLCs circuit, not onchain funds.
+ ChannelMonitorUpdateErr::PermanentFailure => {},
+ ChannelMonitorUpdateErr::TemporaryFailure => {},
+ }
+ }
+ }
+ let mut shutdown_res = chan.force_shutdown();
+ if shutdown_res.0.len() >= 1 {
+ log_error!($self, "You have a toxic local commitment transaction {} avaible in channel monitor, read comment in ChannelMonitor::get_latest_local_commitment_txn to be informed of manual action to take", shutdown_res.0[0].txid());
+ }
+ shutdown_res.0.clear();
+ return Err(MsgHandleErrInternal::from_finish_shutdown(msg, channel_id, shutdown_res, $self.get_channel_update(&chan).ok()))
+ }
}
}
}
/// Non-proportional fees are fixed according to our risk using the provided fee estimator.
///
/// panics if channel_value_satoshis is >= `MAX_FUNDING_SATOSHIS`!
- pub fn new(network: Network, feeest: Arc<FeeEstimator>, monitor: Arc<ManyChannelMonitor>, chain_monitor: Arc<ChainWatchInterface>, tx_broadcaster: Arc<BroadcasterInterface>, logger: Arc<Logger>,keys_manager: Arc<KeysInterface>, config: UserConfig) -> Result<Arc<ChannelManager>, secp256k1::Error> {
+ ///
+ /// User must provide the current blockchain height from which to track onchain channel
+ /// funding outpoints and send payments with reliable timelocks.
+ pub fn new(network: Network, feeest: Arc<FeeEstimator>, monitor: Arc<ManyChannelMonitor>, chain_monitor: Arc<ChainWatchInterface>, tx_broadcaster: Arc<BroadcasterInterface>, logger: Arc<Logger>,keys_manager: Arc<KeysInterface>, config: UserConfig, current_blockchain_height: usize) -> Result<Arc<ChannelManager>, secp256k1::Error> {
let secp_ctx = Secp256k1::new();
let res = Arc::new(ChannelManager {
chain_monitor,
tx_broadcaster,
- latest_block_height: AtomicUsize::new(0), //TODO: Get an init value
+ latest_block_height: AtomicUsize::new(current_blockchain_height),
last_block_hash: Mutex::new(Default::default()),
secp_ctx,
ChannelMonitorUpdateErr::TemporaryFailure => true,
}
} else {
- let (raa, commitment_update, order, pending_forwards, mut pending_failures, needs_broadcast_safe) = channel.monitor_updating_restored();
+ let (raa, commitment_update, order, pending_forwards, mut pending_failures, needs_broadcast_safe, funding_locked) = channel.monitor_updating_restored();
if !pending_forwards.is_empty() {
htlc_forwards.push((channel.get_short_channel_id().expect("We can't have pending forwards before funding confirmation"), pending_forwards));
}
user_channel_id: channel.get_user_id(),
});
}
+ if let Some(msg) = funding_locked {
+ pending_msg_events.push(events::MessageSendEvent::SendFundingLocked {
+ node_id: channel.get_their_node_id(),
+ msg,
+ });
+ if let Some(announcement_sigs) = self.get_announcement_sigs(channel) {
+ pending_msg_events.push(events::MessageSendEvent::SendAnnouncementSignatures {
+ node_id: channel.get_their_node_id(),
+ msg: announcement_sigs,
+ });
+ }
+ short_to_id.insert(channel.get_short_channel_id().unwrap(), channel.channel_id());
+ }
true
}
} else { true }
}
fn internal_funding_created(&self, their_node_id: &PublicKey, msg: &msgs::FundingCreated) -> Result<(), MsgHandleErrInternal> {
- let ((funding_msg, monitor_update), chan) = {
+ let ((funding_msg, monitor_update), mut chan) = {
let mut channel_lock = self.channel_state.lock().unwrap();
let channel_state = channel_lock.borrow_parts();
match channel_state.by_id.entry(msg.temporary_channel_id.clone()) {
};
// Because we have exclusive ownership of the channel here we can release the channel_state
// lock before add_update_monitor
- if let Err(_e) = self.monitor.add_update_monitor(monitor_update.get_funding_txo().unwrap(), monitor_update) {
- unimplemented!();
+ if let Err(e) = self.monitor.add_update_monitor(monitor_update.get_funding_txo().unwrap(), monitor_update) {
+ match e {
+ ChannelMonitorUpdateErr::PermanentFailure => {
+ // Note that we reply with the new channel_id in error messages if we gave up on the
+ // channel, not the temporary_channel_id. This is compatible with ourselves, but the
+ // spec is somewhat ambiguous here. Not a huge deal since we'll send error messages for
+ // any messages referencing a previously-closed channel anyway.
+ return Err(MsgHandleErrInternal::from_finish_shutdown("ChannelMonitor storage failure", funding_msg.channel_id, chan.force_shutdown(), None));
+ },
+ ChannelMonitorUpdateErr::TemporaryFailure => {
+ // There's no problem signing a counterparty's funding transaction if our monitor
+ // 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());
+ },
+ }
}
let mut channel_state_lock = self.channel_state.lock().unwrap();
let channel_state = channel_state_lock.borrow_parts();