use ln::msgs;
use ln::onion_utils;
use ln::msgs::{ChannelMessageHandler, DecodeError, LightningError};
-use chain::keysinterface::{ChannelKeys, KeysInterface};
+use chain::keysinterface::{ChannelKeys, KeysInterface, InMemoryChannelKeys};
use util::config::UserConfig;
use util::{byte_utils, events};
use util::ser::{Readable, ReadableArgs, Writeable, Writer};
use std::sync::{Arc, Mutex, MutexGuard, RwLock};
use std::sync::atomic::{AtomicUsize, Ordering};
use std::time::Duration;
+use std::marker::{Sync, Send};
+use std::ops::Deref;
const SIXTY_FIVE_ZEROS: [u8; 65] = [0; 65];
}
}
#[inline]
- fn from_chan_no_close(err: ChannelError, channel_id: [u8; 32]) -> Self {
+ fn from_chan_no_close<ChanSigner: ChannelKeys>(err: ChannelError<ChanSigner>, channel_id: [u8; 32]) -> Self {
Self {
err: match err {
ChannelError::Ignore(msg) => LightningError {
pub(super) pending_msg_events: Vec<events::MessageSendEvent>,
}
+/// State we hold per-peer. In the future we should put channels in here, but for now we only hold
+/// the latest Init features we heard from the peer.
+struct PeerState {
+ latest_features: InitFeatures,
+}
+
#[cfg(not(any(target_pointer_width = "32", target_pointer_width = "64")))]
const ERR: () = "You need at least 32 bit pointers (well, usize, but we'll assume they're the same) for ChannelManager::latest_block_height";
+/// SimpleArcChannelManager is useful when you need a ChannelManager with a static lifetime, e.g.
+/// when you're using lightning-net-tokio (since tokio::spawn requires parameters with static
+/// lifetimes). Other times you can afford a reference, which is more efficient, in which case
+/// SimpleRefChannelManager is the more appropriate type. Defining these type aliases prevents
+/// issues such as overly long function definitions.
+pub type SimpleArcChannelManager<M> = Arc<ChannelManager<InMemoryChannelKeys, Arc<M>>>;
+
+/// SimpleRefChannelManager is a type alias for a ChannelManager reference, and is the reference
+/// counterpart to the SimpleArcChannelManager type alias. Use this type by default when you don't
+/// need a ChannelManager with a static lifetime. You'll need a static lifetime in cases such as
+/// usage of lightning-net-tokio (since tokio::spawn requires parameters with static lifetimes).
+/// But if this is not necessary, using a reference is more efficient. Defining these type aliases
+/// helps with issues such as long function definitions.
+pub type SimpleRefChannelManager<'a, M> = ChannelManager<InMemoryChannelKeys, &'a M>;
+
/// Manager which keeps track of a number of channels and sends messages to the appropriate
/// channel, also tracking HTLC preimages and forwarding onion packets appropriately.
///
/// ChannelUpdate messages informing peers that the channel is temporarily disabled. To avoid
/// spam due to quick disconnection/reconnection, updates are not sent until the channel has been
/// offline for a full minute. In order to track this, you must call
-/// timer_chan_freshness_every_min roughly once per minute, though it doesn't have to be perfec.
-pub struct ChannelManager<ChanSigner: ChannelKeys> {
+/// timer_chan_freshness_every_min roughly once per minute, though it doesn't have to be perfect.
+///
+/// Rather than using a plain ChannelManager, it is preferable to use either a SimpleArcChannelManager
+/// a SimpleRefChannelManager, for conciseness. See their documentation for more details, but
+/// essentially you should default to using a SimpleRefChannelManager, and use a
+/// SimpleArcChannelManager when you require a ChannelManager with a static lifetime, such as when
+/// you're using lightning-net-tokio.
+pub struct ChannelManager<ChanSigner: ChannelKeys, M: Deref> where M::Target: ManyChannelMonitor<ChanSigner> {
default_configuration: UserConfig,
genesis_hash: Sha256dHash,
fee_estimator: Arc<FeeEstimator>,
- monitor: Arc<ManyChannelMonitor>,
+ monitor: M,
tx_broadcaster: Arc<BroadcasterInterface>,
#[cfg(test)]
channel_state: Mutex<ChannelHolder<ChanSigner>>,
our_network_key: SecretKey,
+ /// The bulk of our storage will eventually be here (channels and message queues and the like).
+ /// If we are connected to a peer we always at least have an entry here, even if no channels
+ /// are currently open with that peer.
+ /// Because adding or removing an entry is rare, we usually take an outer read lock and then
+ /// operate on the inner value freely. Sadly, this prevents parallel operation when opening a
+ /// new channel.
+ per_peer_state: RwLock<HashMap<PublicKey, Mutex<PeerState>>>,
+
pending_events: Mutex<Vec<events::Event>>,
/// Used when we have to take a BIG lock to make sure everything is self-consistent.
/// Essentially just when we're serializing ourselves out.
pub short_channel_id: Option<u64>,
/// The node_id of our counterparty
pub remote_network_id: PublicKey,
+ /// The Features the channel counterparty provided upon last connection.
+ /// Useful for routing as it is the most up-to-date copy of the counterparty's features and
+ /// many routing-relevant features are present in the init context.
+ pub counterparty_features: InitFeatures,
/// The value, in satoshis, of this channel as appears in the funding output
pub channel_value_satoshis: u64,
/// The user_id passed in to create_channel, or 0 if the channel was inbound.
match $res {
Ok(res) => res,
Err(ChannelError::Ignore(msg)) => {
- break Err(MsgHandleErrInternal::from_chan_no_close(ChannelError::Ignore(msg), $entry.key().clone()))
+ break Err(MsgHandleErrInternal::from_chan_no_close::<ChanSigner>(ChannelError::Ignore(msg), $entry.key().clone()))
},
Err(ChannelError::Close(msg)) => {
log_trace!($self, "Closing channel {} due to Close-required error: {}", log_bytes!($entry.key()[..]), msg);
match $res {
Ok(res) => res,
Err(ChannelError::Ignore(msg)) => {
- return Err(MsgHandleErrInternal::from_chan_no_close(ChannelError::Ignore(msg), $entry.key().clone()))
+ return Err(MsgHandleErrInternal::from_chan_no_close::<ChanSigner>(ChannelError::Ignore(msg), $entry.key().clone()))
},
Err(ChannelError::Close(msg)) => {
log_trace!($self, "Closing channel {} due to Close-required error: {}", log_bytes!($entry.key()[..]), msg);
$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) {
+ if let Err(e) = $self.monitor.add_update_monitor(update.get_funding_txo().unwrap(), update.clone()) {
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
debug_assert!($action_type == RAACommitmentOrder::CommitmentFirst || !$resend_commitment);
}
$entry.get_mut().monitor_update_failed($resend_raa, $resend_commitment, $failed_forwards, $failed_fails);
- Err(MsgHandleErrInternal::from_chan_no_close(ChannelError::Ignore("Failed to update ChannelMonitor"), *$entry.key()))
+ Err(MsgHandleErrInternal::from_chan_no_close::<ChanSigner>(ChannelError::Ignore("Failed to update ChannelMonitor"), *$entry.key()))
},
}
}
}
}
-impl<ChanSigner: ChannelKeys> ChannelManager<ChanSigner> {
+impl<ChanSigner: ChannelKeys, M: Deref> ChannelManager<ChanSigner, M> where M::Target: ManyChannelMonitor<ChanSigner> {
/// Constructs a new ChannelManager to hold several channels and route between them.
///
/// This is the main "logic hub" for all channel-related actions, and implements
/// the ChannelManager as a listener to the BlockNotifier and call the BlockNotifier's
/// `block_(dis)connected` methods, which will notify all registered listeners in one
/// go.
- pub fn new(network: Network, feeest: Arc<FeeEstimator>, monitor: Arc<ManyChannelMonitor>, tx_broadcaster: Arc<BroadcasterInterface>, logger: Arc<Logger>,keys_manager: Arc<KeysInterface<ChanKeySigner = ChanSigner>>, config: UserConfig, current_blockchain_height: usize) -> Result<Arc<ChannelManager<ChanSigner>>, secp256k1::Error> {
+ pub fn new(network: Network, feeest: Arc<FeeEstimator>, monitor: M, tx_broadcaster: Arc<BroadcasterInterface>, logger: Arc<Logger>,keys_manager: Arc<KeysInterface<ChanKeySigner = ChanSigner>>, config: UserConfig, current_blockchain_height: usize) -> Result<ChannelManager<ChanSigner, M>, secp256k1::Error> {
let secp_ctx = Secp256k1::new();
- let res = Arc::new(ChannelManager {
+ let res = ChannelManager {
default_configuration: config.clone(),
genesis_hash: genesis_block(network).header.bitcoin_hash(),
fee_estimator: feeest.clone(),
- monitor: monitor.clone(),
+ monitor,
tx_broadcaster,
latest_block_height: AtomicUsize::new(current_blockchain_height),
}),
our_network_key: keys_manager.get_node_secret(),
+ per_peer_state: RwLock::new(HashMap::new()),
+
pending_events: Mutex::new(Vec::new()),
total_consistency_lock: RwLock::new(()),
keys_manager,
logger,
- });
+ };
Ok(res)
}
Ok(())
}
- /// Gets the list of open channels, in random order. See ChannelDetail field documentation for
- /// more information.
- pub fn list_channels(&self) -> Vec<ChannelDetails> {
- let channel_state = self.channel_state.lock().unwrap();
- let mut res = Vec::with_capacity(channel_state.by_id.len());
- for (channel_id, channel) in channel_state.by_id.iter() {
- let (inbound_capacity_msat, outbound_capacity_msat) = channel.get_inbound_outbound_available_balance_msat();
- res.push(ChannelDetails {
- channel_id: (*channel_id).clone(),
- short_channel_id: channel.get_short_channel_id(),
- remote_network_id: channel.get_their_node_id(),
- channel_value_satoshis: channel.get_value_satoshis(),
- inbound_capacity_msat,
- outbound_capacity_msat,
- user_id: channel.get_user_id(),
- is_live: channel.is_live(),
- });
- }
- res
- }
-
- /// Gets the list of usable channels, in random order. Useful as an argument to
- /// Router::get_route to ensure non-announced channels are used.
- ///
- /// These are guaranteed to have their is_live value set to true, see the documentation for
- /// ChannelDetails::is_live for more info on exactly what the criteria are.
- pub fn list_usable_channels(&self) -> Vec<ChannelDetails> {
- let channel_state = self.channel_state.lock().unwrap();
- let mut res = Vec::with_capacity(channel_state.by_id.len());
- for (channel_id, channel) in channel_state.by_id.iter() {
- // Note we use is_live here instead of usable which leads to somewhat confused
- // internal/external nomenclature, but that's ok cause that's probably what the user
- // really wanted anyway.
- if channel.is_live() {
+ fn list_channels_with_filter<F: FnMut(&(&[u8; 32], &Channel<ChanSigner>)) -> bool>(&self, f: F) -> Vec<ChannelDetails> {
+ let mut res = Vec::new();
+ {
+ let channel_state = self.channel_state.lock().unwrap();
+ res.reserve(channel_state.by_id.len());
+ for (channel_id, channel) in channel_state.by_id.iter().filter(f) {
let (inbound_capacity_msat, outbound_capacity_msat) = channel.get_inbound_outbound_available_balance_msat();
res.push(ChannelDetails {
channel_id: (*channel_id).clone(),
short_channel_id: channel.get_short_channel_id(),
remote_network_id: channel.get_their_node_id(),
+ counterparty_features: InitFeatures::empty(),
channel_value_satoshis: channel.get_value_satoshis(),
inbound_capacity_msat,
outbound_capacity_msat,
user_id: channel.get_user_id(),
- is_live: true,
+ is_live: channel.is_live(),
});
}
}
+ let per_peer_state = self.per_peer_state.read().unwrap();
+ for chan in res.iter_mut() {
+ if let Some(peer_state) = per_peer_state.get(&chan.remote_network_id) {
+ chan.counterparty_features = peer_state.lock().unwrap().latest_features.clone();
+ }
+ }
res
}
+ /// Gets the list of open channels, in random order. See ChannelDetail field documentation for
+ /// more information.
+ pub fn list_channels(&self) -> Vec<ChannelDetails> {
+ self.list_channels_with_filter(|_| true)
+ }
+
+ /// Gets the list of usable channels, in random order. Useful as an argument to
+ /// Router::get_route to ensure non-announced channels are used.
+ ///
+ /// These are guaranteed to have their is_live value set to true, see the documentation for
+ /// ChannelDetails::is_live for more info on exactly what the criteria are.
+ pub fn list_usable_channels(&self) -> Vec<ChannelDetails> {
+ // Note we use is_live here instead of usable which leads to somewhat confused
+ // internal/external nomenclature, but that's ok cause that's probably what the user
+ // really wanted anyway.
+ self.list_channels_with_filter(|&(_, ref channel)| channel.is_live())
+ }
+
/// Begins the process of closing a channel. After this call (plus some timeout), no new HTLCs
/// will be accepted on the given channel, and after additional timeout/the closing of all
/// pending HTLCs, the channel will be closed on chain.
return_err!("The final CLTV expiry is too soon to handle", 17, &[0;0]);
}
// final_incorrect_htlc_amount
- if next_hop_data.data.amt_to_forward > msg.amount_msat {
+ if next_hop_data.amt_to_forward > msg.amount_msat {
return_err!("Upstream node sent less than we were supposed to receive in payment", 19, &byte_utils::be64_to_array(msg.amount_msat));
}
// final_incorrect_cltv_expiry
- if next_hop_data.data.outgoing_cltv_value != msg.cltv_expiry {
+ if next_hop_data.outgoing_cltv_value != msg.cltv_expiry {
return_err!("Upstream node set CLTV to the wrong value", 18, &byte_utils::be32_to_array(msg.cltv_expiry));
}
payment_hash: msg.payment_hash.clone(),
short_channel_id: 0,
incoming_shared_secret: shared_secret,
- amt_to_forward: next_hop_data.data.amt_to_forward,
- outgoing_cltv_value: next_hop_data.data.outgoing_cltv_value,
+ amt_to_forward: next_hop_data.amt_to_forward,
+ outgoing_cltv_value: next_hop_data.outgoing_cltv_value,
})
} else {
let mut new_packet_data = [0; 20*65];
PendingHTLCStatus::Forward(PendingForwardHTLCInfo {
onion_packet: Some(outgoing_packet),
payment_hash: msg.payment_hash.clone(),
- short_channel_id: next_hop_data.data.short_channel_id,
+ short_channel_id: next_hop_data.short_channel_id,
incoming_shared_secret: shared_secret,
- amt_to_forward: next_hop_data.data.amt_to_forward,
- outgoing_cltv_value: next_hop_data.data.outgoing_cltv_value,
+ amt_to_forward: next_hop_data.amt_to_forward,
+ outgoing_cltv_value: next_hop_data.outgoing_cltv_value,
})
};
}
fn get_announcement_sigs(&self, chan: &Channel<ChanSigner>) -> Option<msgs::AnnouncementSignatures> {
- if !chan.should_announce() { return None }
+ if !chan.should_announce() {
+ log_trace!(self, "Can't send announcement_signatures for private channel {}", log_bytes!(chan.channel_id()));
+ return None
+ }
let (announcement, our_bitcoin_sig) = match chan.get_channel_announcement(self.get_our_node_id(), self.genesis_hash.clone()) {
Ok(res) => res,
}
try_chan_entry!(self, chan.get_mut().funding_locked(&msg), channel_state, chan);
if let Some(announcement_sigs) = self.get_announcement_sigs(chan.get()) {
+ log_trace!(self, "Sending announcement_signatures for {} in response to funding_locked", log_bytes!(chan.get().channel_id()));
// If we see locking block before receiving remote funding_locked, we broadcast our
// announcement_sigs at remote funding_locked reception. If we receive remote
// funding_locked before seeing locking block, we broadcast our announcement_sigs at locking
return Err(MsgHandleErrInternal::send_err_msg_no_close("Got a message for a channel from the wrong node!", msg.channel_id));
}
if (msg.failure_code & 0x8000) == 0 {
- try_chan_entry!(self, Err(ChannelError::Close("Got update_fail_malformed_htlc with BADONION not set")), channel_state, chan);
+ let chan_err: ChannelError<ChanSigner> = ChannelError::Close("Got update_fail_malformed_htlc with BADONION not set");
+ try_chan_entry!(self, Err(chan_err), channel_state, chan);
}
try_chan_entry!(self, chan.get_mut().update_fail_malformed_htlc(&msg, HTLCFailReason::Reason { failure_code: msg.failure_code, data: Vec::new() }), channel_state, chan);
Ok(())
let msghash = hash_to_message!(&Sha256dHash::hash(&announcement.encode()[..])[..]);
if self.secp_ctx.verify(&msghash, &msg.node_signature, if were_node_one { &announcement.node_id_2 } else { &announcement.node_id_1 }).is_err() ||
self.secp_ctx.verify(&msghash, &msg.bitcoin_signature, if were_node_one { &announcement.bitcoin_key_2 } else { &announcement.bitcoin_key_1 }).is_err() {
- try_chan_entry!(self, Err(ChannelError::Close("Bad announcement_signatures node_signature")), channel_state, chan);
+ let chan_err: ChannelError<ChanSigner> = ChannelError::Close("Bad announcement_signatures node_signature");
+ try_chan_entry!(self, Err(chan_err), channel_state, chan);
}
let our_node_sig = self.secp_ctx.sign(&msghash, &self.our_network_key);
}
}
-impl<ChanSigner: ChannelKeys> events::MessageSendEventsProvider for ChannelManager<ChanSigner> {
+impl<ChanSigner: ChannelKeys, M: Deref> events::MessageSendEventsProvider for ChannelManager<ChanSigner, M> where M::Target: ManyChannelMonitor<ChanSigner> {
fn get_and_clear_pending_msg_events(&self) -> Vec<events::MessageSendEvent> {
// TODO: Event release to users and serialization is currently race-y: it's very easy for a
// user to serialize a ChannelManager with pending events in it and lose those events on
}
}
-impl<ChanSigner: ChannelKeys> events::EventsProvider for ChannelManager<ChanSigner> {
+impl<ChanSigner: ChannelKeys, M: Deref> events::EventsProvider for ChannelManager<ChanSigner, M> where M::Target: ManyChannelMonitor<ChanSigner> {
fn get_and_clear_pending_events(&self) -> Vec<events::Event> {
// TODO: Event release to users and serialization is currently race-y: it's very easy for a
// user to serialize a ChannelManager with pending events in it and lose those events on
}
}
-impl<ChanSigner: ChannelKeys> ChainListener for ChannelManager<ChanSigner> {
+impl<ChanSigner: ChannelKeys, M: Deref + Sync + Send> ChainListener for ChannelManager<ChanSigner, M> where M::Target: ManyChannelMonitor<ChanSigner> {
fn block_connected(&self, header: &BlockHeader, height: u32, txn_matched: &[&Transaction], indexes_of_txn_matched: &[u32]) {
let header_hash = header.bitcoin_hash();
log_trace!(self, "Block {} at height {} connected with {} txn matched", header_hash, height, txn_matched.len());
msg: funding_locked,
});
if let Some(announcement_sigs) = self.get_announcement_sigs(channel) {
+ log_trace!(self, "Sending funding_locked and announcement_signatures for {}", log_bytes!(channel.channel_id()));
pending_msg_events.push(events::MessageSendEvent::SendAnnouncementSignatures {
node_id: channel.get_their_node_id(),
msg: announcement_sigs,
});
+ } else {
+ log_trace!(self, "Sending funding_locked WITHOUT announcement_signatures for {}", log_bytes!(channel.channel_id()));
}
short_to_id.insert(channel.get_short_channel_id().unwrap(), channel.channel_id());
} else if let Err(e) = chan_res {
}
}
-impl<ChanSigner: ChannelKeys> ChannelMessageHandler for ChannelManager<ChanSigner> {
+impl<ChanSigner: ChannelKeys, M: Deref + Sync + Send> ChannelMessageHandler for ChannelManager<ChanSigner, M> where M::Target: ManyChannelMonitor<ChanSigner> {
fn handle_open_channel(&self, their_node_id: &PublicKey, their_features: InitFeatures, msg: &msgs::OpenChannel) {
let _ = self.total_consistency_lock.read().unwrap();
let res = self.internal_open_channel(their_node_id, their_features, msg);
let _ = self.total_consistency_lock.read().unwrap();
let mut failed_channels = Vec::new();
let mut failed_payments = Vec::new();
+ let mut no_channels_remain = true;
{
let mut channel_state_lock = self.channel_state.lock().unwrap();
let channel_state = &mut *channel_state_lock;
short_to_id.remove(&short_id);
}
return false;
+ } else {
+ no_channels_remain = false;
}
}
true
}
});
}
+ if no_channels_remain {
+ self.per_peer_state.write().unwrap().remove(their_node_id);
+ }
+
for failure in failed_channels.drain(..) {
self.finish_force_close_channel(failure);
}
}
}
- fn peer_connected(&self, their_node_id: &PublicKey) {
+ fn peer_connected(&self, their_node_id: &PublicKey, init_msg: &msgs::Init) {
log_debug!(self, "Generating channel_reestablish events for {}", log_pubkey!(their_node_id));
let _ = self.total_consistency_lock.read().unwrap();
+
+ {
+ let mut peer_state_lock = self.per_peer_state.write().unwrap();
+ match peer_state_lock.entry(their_node_id.clone()) {
+ hash_map::Entry::Vacant(e) => {
+ e.insert(Mutex::new(PeerState {
+ latest_features: init_msg.features.clone(),
+ }));
+ },
+ hash_map::Entry::Occupied(e) => {
+ e.get().lock().unwrap().latest_features = init_msg.features.clone();
+ },
+ }
+ }
+
let mut channel_state_lock = self.channel_state.lock().unwrap();
let channel_state = &mut *channel_state_lock;
let pending_msg_events = &mut channel_state.pending_msg_events;
}
}
-impl<ChanSigner: ChannelKeys + Writeable> Writeable for ChannelManager<ChanSigner> {
+impl<ChanSigner: ChannelKeys + Writeable, M: Deref> Writeable for ChannelManager<ChanSigner, M> where M::Target: ManyChannelMonitor<ChanSigner> {
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
let _ = self.total_consistency_lock.write().unwrap();
}
}
+ let per_peer_state = self.per_peer_state.write().unwrap();
+ (per_peer_state.len() as u64).write(writer)?;
+ for (peer_pubkey, peer_state_mutex) in per_peer_state.iter() {
+ peer_pubkey.write(writer)?;
+ let peer_state = peer_state_mutex.lock().unwrap();
+ peer_state.latest_features.write(writer)?;
+ }
+
Ok(())
}
}
/// 5) Move the ChannelMonitors into your local ManyChannelMonitor.
/// 6) Disconnect/connect blocks on the ChannelManager.
/// 7) Register the new ChannelManager with your ChainWatchInterface.
-pub struct ChannelManagerReadArgs<'a, ChanSigner: ChannelKeys> {
+pub struct ChannelManagerReadArgs<'a, ChanSigner: 'a + ChannelKeys, M: Deref> where M::Target: ManyChannelMonitor<ChanSigner> {
/// The keys provider which will give us relevant keys. Some keys will be loaded during
/// deserialization.
pub keys_manager: Arc<KeysInterface<ChanKeySigner = ChanSigner>>,
/// No calls to the ManyChannelMonitor will be made during deserialization. It is assumed that
/// you have deserialized ChannelMonitors separately and will add them to your
/// ManyChannelMonitor after deserializing this ChannelManager.
- pub monitor: Arc<ManyChannelMonitor>,
+ pub monitor: M,
/// The BroadcasterInterface which will be used in the ChannelManager in the future and may be
/// used to broadcast the latest local commitment transactions of channels which must be
///
/// In such cases the latest local transactions will be sent to the tx_broadcaster included in
/// this struct.
- pub channel_monitors: &'a mut HashMap<OutPoint, &'a mut ChannelMonitor>,
+ pub channel_monitors: &'a mut HashMap<OutPoint, &'a mut ChannelMonitor<ChanSigner>>,
}
-impl<'a, R : ::std::io::Read, ChanSigner: ChannelKeys + Readable<R>> ReadableArgs<R, ChannelManagerReadArgs<'a, ChanSigner>> for (Sha256dHash, ChannelManager<ChanSigner>) {
- fn read(reader: &mut R, args: ChannelManagerReadArgs<'a, ChanSigner>) -> Result<Self, DecodeError> {
+impl<'a, R : ::std::io::Read, ChanSigner: ChannelKeys + Readable<R>, M: Deref> ReadableArgs<R, ChannelManagerReadArgs<'a, ChanSigner, M>> for (Sha256dHash, ChannelManager<ChanSigner, M>) where M::Target: ManyChannelMonitor<ChanSigner> {
+ fn read(reader: &mut R, args: ChannelManagerReadArgs<'a, ChanSigner, M>) -> Result<Self, DecodeError> {
let _ver: u8 = Readable::read(reader)?;
let min_ver: u8 = Readable::read(reader)?;
if min_ver > SERIALIZATION_VERSION {
claimable_htlcs.insert(payment_hash, previous_hops);
}
+ let peer_count: u64 = Readable::read(reader)?;
+ let mut per_peer_state = HashMap::with_capacity(cmp::min(peer_count as usize, 128));
+ for _ in 0..peer_count {
+ let peer_pubkey = Readable::read(reader)?;
+ let peer_state = PeerState {
+ latest_features: Readable::read(reader)?,
+ };
+ per_peer_state.insert(peer_pubkey, Mutex::new(peer_state));
+ }
+
let channel_manager = ChannelManager {
genesis_hash,
fee_estimator: args.fee_estimator,
}),
our_network_key: args.keys_manager.get_node_secret(),
+ per_peer_state: RwLock::new(per_peer_state),
+
pending_events: Mutex::new(Vec::new()),
total_consistency_lock: RwLock::new(()),
keys_manager: args.keys_manager,