use bitcoin::secp256k1;
use chain;
-use chain::Confirm;
-use chain::Watch;
+use chain::{Confirm, Watch, BestBlock};
use chain::chaininterface::{BroadcasterInterface, FeeEstimator};
use chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateStep, ChannelMonitorUpdateErr, HTLC_FAIL_BACK_BUFFER, CLTV_CLAIM_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS, ANTI_REORG_DELAY, MonitorEvent, CLOSED_CHANNEL_UPDATE_ID};
use chain::transaction::{OutPoint, TransactionData};
// construct one themselves.
use ln::{PaymentHash, PaymentPreimage, PaymentSecret};
pub use ln::channel::CounterpartyForwardingInfo;
-use ln::channel::{Channel, ChannelError, ChannelUpdateStatus};
+use ln::channel::{Channel, ChannelError, ChannelUpdateStatus, UpdateFulfillCommitFetch};
use ln::features::{InitFeatures, NodeFeatures};
use routing::router::{Route, RouteHop};
use ln::msgs;
use util::{byte_utils, events};
use util::ser::{Readable, ReadableArgs, MaybeReadable, Writeable, Writer};
use util::chacha20::{ChaCha20, ChaChaReader};
-use util::logger::Logger;
+use util::logger::{Logger, Level};
use util::errors::APIError;
use prelude::*;
pub best_block: BestBlock,
}
-/// The best known block as identified by its hash and height.
-#[derive(Clone, Copy, PartialEq)]
-pub struct BestBlock {
- block_hash: BlockHash,
- height: u32,
-}
-
-impl BestBlock {
- /// Returns the best block from the genesis of the given network.
- pub fn from_genesis(network: Network) -> Self {
- BestBlock {
- block_hash: genesis_block(network).header.block_hash(),
- height: 0,
- }
- }
-
- /// Returns the best block as identified by the given block hash and height.
- pub fn new(block_hash: BlockHash, height: u32) -> Self {
- BestBlock { block_hash, height }
- }
-
- /// Returns the best block hash.
- pub fn block_hash(&self) -> BlockHash { self.block_hash }
-
- /// Returns the best block height.
- pub fn height(&self) -> u32 { self.height }
-}
-
#[derive(Copy, Clone, PartialEq)]
enum NotifyOption {
DoPersist,
};
if let hash_map::Entry::Occupied(mut chan) = channel_state.by_id.entry(chan_id) {
- let was_frozen_for_monitor = chan.get().is_awaiting_monitor_update();
match chan.get_mut().get_update_fulfill_htlc_and_commit(prev_hop.htlc_id, payment_preimage, &self.logger) {
- Ok((msgs, monitor_option)) => {
- if let Some(monitor_update) = monitor_option {
+ Ok(msgs_monitor_option) => {
+ if let UpdateFulfillCommitFetch::NewClaim { msgs, monitor_update } = msgs_monitor_option {
if let Err(e) = self.chain_monitor.update_channel(chan.get().get_funding_txo().unwrap(), monitor_update) {
- if was_frozen_for_monitor {
- assert!(msgs.is_none());
- } else {
- return Err(Some((chan.get().get_counterparty_node_id(), handle_monitor_err!(self, e, channel_state, chan, RAACommitmentOrder::CommitmentFirst, false, msgs.is_some()).unwrap_err())));
- }
+ log_given_level!(self.logger, if e == ChannelMonitorUpdateErr::PermanentFailure { Level::Error } else { Level::Debug },
+ "Failed to update channel monitor with preimage {:?}: {:?}",
+ payment_preimage, e);
+ return Err(Some((
+ chan.get().get_counterparty_node_id(),
+ handle_monitor_err!(self, e, channel_state, chan, RAACommitmentOrder::CommitmentFirst, false, msgs.is_some()).unwrap_err(),
+ )));
+ }
+ if let Some((msg, commitment_signed)) = msgs {
+ log_debug!(self.logger, "Claiming funds for HTLC with preimage {} resulted in a commitment_signed for channel {}",
+ log_bytes!(payment_preimage.0), log_bytes!(chan.get().channel_id()));
+ channel_state.pending_msg_events.push(events::MessageSendEvent::UpdateHTLCs {
+ node_id: chan.get().get_counterparty_node_id(),
+ updates: msgs::CommitmentUpdate {
+ update_add_htlcs: Vec::new(),
+ update_fulfill_htlcs: vec![msg],
+ update_fail_htlcs: Vec::new(),
+ update_fail_malformed_htlcs: Vec::new(),
+ update_fee: None,
+ commitment_signed,
+ }
+ });
}
- }
- if let Some((msg, commitment_signed)) = msgs {
- log_debug!(self.logger, "Claiming funds for HTLC with preimage {} resulted in a commitment_signed for channel {}",
- log_bytes!(payment_preimage.0), log_bytes!(chan.get().channel_id()));
- channel_state.pending_msg_events.push(events::MessageSendEvent::UpdateHTLCs {
- node_id: chan.get().get_counterparty_node_id(),
- updates: msgs::CommitmentUpdate {
- update_add_htlcs: Vec::new(),
- update_fulfill_htlcs: vec![msg],
- update_fail_htlcs: Vec::new(),
- update_fail_malformed_htlcs: Vec::new(),
- update_fee: None,
- commitment_signed,
- }
- });
}
return Ok(())
},
- Err(e) => {
- // TODO: Do something with e?
- // This should only occur if we are claiming an HTLC at the same time as the
- // HTLC is being failed (eg because a block is being connected and this caused
- // an HTLC to time out). This should, of course, only occur if the user is the
- // one doing the claiming (as it being a part of a peer claim would imply we're
- // about to lose funds) and only if the lock in claim_funds was dropped as a
- // previous HTLC was failed (thus not for an MPP payment).
- debug_assert!(false, "This shouldn't be reachable except in absurdly rare cases between monitor updates and HTLC timeouts: {:?}", e);
- return Err(None)
+ Err((e, monitor_update)) => {
+ if let Err(e) = self.chain_monitor.update_channel(chan.get().get_funding_txo().unwrap(), monitor_update) {
+ log_given_level!(self.logger, if e == ChannelMonitorUpdateErr::PermanentFailure { Level::Error } else { Level::Info },
+ "Failed to update channel monitor with preimage {:?} immediately prior to force-close: {:?}",
+ payment_preimage, e);
+ }
+ let counterparty_node_id = chan.get().get_counterparty_node_id();
+ let (drop, res) = convert_chan_err!(self, e, channel_state.short_to_id, chan.get_mut(), &chan_id);
+ if drop {
+ chan.remove_entry();
+ }
+ return Err(Some((counterparty_node_id, res)));
},
}
} else { unreachable!(); }
let guard = mtx.lock().unwrap();
*guard
}
+
+ /// Gets the latest best block which was connected either via the [`chain::Listen`] or
+ /// [`chain::Confirm`] interfaces.
+ pub fn current_best_block(&self) -> BestBlock {
+ self.best_block.read().unwrap().clone()
+ }
}
impl<Signer: Sign, M: Deref , T: Deref , K: Deref , F: Deref , L: Deref >