use util::logger::Logger;
use util::errors::APIError;
+use prelude::*;
use core::{cmp, mem};
-use std::cell::RefCell;
+use core::cell::RefCell;
use std::collections::{HashMap, hash_map, HashSet};
use std::io::{Cursor, Read};
use std::sync::{Arc, Condvar, Mutex, MutexGuard, RwLock, RwLockReadGuard};
// smaller than 500:
const STATIC_ASSERT: u32 = Self::HALF_MESSAGE_IS_ADDRS - 500;
- /// Generates a signed node_announcement from the given arguments and creates a
- /// BroadcastNodeAnnouncement event. Note that such messages will be ignored unless peers have
- /// seen a channel_announcement from us (ie unless we have public channels open).
+ /// Regenerates channel_announcements and generates a signed node_announcement from the given
+ /// arguments, providing them in corresponding events via
+ /// [`get_and_clear_pending_msg_events`], if at least one public channel has been confirmed
+ /// on-chain. This effectively re-broadcasts all channel announcements and sends our node
+ /// announcement to ensure that the lightning P2P network is aware of the channels we have and
+ /// our network addresses.
///
- /// RGB is a node "color" and alias is a printable human-readable string to describe this node
- /// to humans. They carry no in-protocol meaning.
+ /// `rgb` is a node "color" and `alias` is a printable human-readable string to describe this
+ /// node to humans. They carry no in-protocol meaning.
///
- /// addresses represent the set (possibly empty) of socket addresses on which this node accepts
- /// incoming connections. These will be broadcast to the network, publicly tying these
- /// addresses together. If you wish to preserve user privacy, addresses should likely contain
- /// only Tor Onion addresses.
+ /// `addresses` represent the set (possibly empty) of socket addresses on which this node
+ /// accepts incoming connections. These will be included in the node_announcement, publicly
+ /// tying these addresses together and to this node. If you wish to preserve user privacy,
+ /// addresses should likely contain only Tor Onion addresses.
///
- /// Panics if addresses is absurdly large (more than 500).
+ /// Panics if `addresses` is absurdly large (more than 500).
+ ///
+ /// [`get_and_clear_pending_msg_events`]: MessageSendEventsProvider::get_and_clear_pending_msg_events
pub fn broadcast_node_announcement(&self, rgb: [u8; 3], alias: [u8; 32], mut addresses: Vec<NetAddress>) {
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(&self.total_consistency_lock, &self.persistence_notifier);
excess_data: Vec::new(),
};
let msghash = hash_to_message!(&Sha256dHash::hash(&announcement.encode()[..])[..]);
+ let node_announce_sig = self.secp_ctx.sign(&msghash, &self.our_network_key);
- let mut channel_state = self.channel_state.lock().unwrap();
- channel_state.pending_msg_events.push(events::MessageSendEvent::BroadcastNodeAnnouncement {
- msg: msgs::NodeAnnouncement {
- signature: self.secp_ctx.sign(&msghash, &self.our_network_key),
- contents: announcement
- },
- });
+ let mut channel_state_lock = self.channel_state.lock().unwrap();
+ let channel_state = &mut *channel_state_lock;
+
+ let mut announced_chans = false;
+ for (_, chan) in channel_state.by_id.iter() {
+ if let Some(msg) = chan.get_signed_channel_announcement(&self.our_network_key, self.get_our_node_id(), self.genesis_hash.clone()) {
+ channel_state.pending_msg_events.push(events::MessageSendEvent::BroadcastChannelAnnouncement {
+ msg,
+ update_msg: match self.get_channel_update(chan) {
+ Ok(msg) => msg,
+ Err(_) => continue,
+ },
+ });
+ announced_chans = true;
+ } else {
+ // If the channel is not public or has not yet reached funding_locked, check the
+ // next channel. If we don't yet have any public channels, we'll skip the broadcast
+ // below as peers may not accept it without channels on chain first.
+ }
+ }
+
+ if announced_chans {
+ channel_state.pending_msg_events.push(events::MessageSendEvent::BroadcastNodeAnnouncement {
+ msg: msgs::NodeAnnouncement {
+ signature: node_announce_sig,
+ contents: announcement
+ },
+ });
+ }
}
/// Processes HTLCs which are pending waiting on random forward delay.
}
#[cfg(any(test, feature = "_test_utils"))]
- pub(crate) fn test_process_background_events(&self) {
+ /// Process background events, for functional testing
+ pub fn test_process_background_events(&self) {
self.process_background_events();
}
return Err(MsgHandleErrInternal::from_no_close(LightningError{err: "Got an announcement_signatures before we were ready for it".to_owned(), action: msgs::ErrorAction::IgnoreError}));
}
- let our_node_id = self.get_our_node_id();
- let (announcement, our_bitcoin_sig) =
- try_chan_entry!(self, chan.get_mut().get_channel_announcement(our_node_id.clone(), self.genesis_hash.clone()), channel_state, chan);
-
- let were_node_one = announcement.node_id_1 == our_node_id;
- let msghash = hash_to_message!(&Sha256dHash::hash(&announcement.encode()[..])[..]);
- {
- let their_node_key = if were_node_one { &announcement.node_id_2 } else { &announcement.node_id_1 };
- let their_bitcoin_key = if were_node_one { &announcement.bitcoin_key_2 } else { &announcement.bitcoin_key_1 };
- match (self.secp_ctx.verify(&msghash, &msg.node_signature, their_node_key),
- self.secp_ctx.verify(&msghash, &msg.bitcoin_signature, their_bitcoin_key)) {
- (Err(e), _) => {
- let chan_err: ChannelError = ChannelError::Close(format!("Bad announcement_signatures. Failed to verify node_signature: {:?}. Maybe using different node_secret for transport and routing msg? UnsignedChannelAnnouncement used for verification is {:?}. their_node_key is {:?}", e, &announcement, their_node_key));
- try_chan_entry!(self, Err(chan_err), channel_state, chan);
- },
- (_, Err(e)) => {
- let chan_err: ChannelError = ChannelError::Close(format!("Bad announcement_signatures. Failed to verify bitcoin_signature: {:?}. UnsignedChannelAnnouncement used for verification is {:?}. their_bitcoin_key is ({:?})", e, &announcement, their_bitcoin_key));
- try_chan_entry!(self, Err(chan_err), channel_state, chan);
- },
- _ => {}
- }
- }
-
- let our_node_sig = self.secp_ctx.sign(&msghash, &self.our_network_key);
-
channel_state.pending_msg_events.push(events::MessageSendEvent::BroadcastChannelAnnouncement {
- msg: msgs::ChannelAnnouncement {
- node_signature_1: if were_node_one { our_node_sig } else { msg.node_signature },
- node_signature_2: if were_node_one { msg.node_signature } else { our_node_sig },
- bitcoin_signature_1: if were_node_one { our_bitcoin_sig } else { msg.bitcoin_signature },
- bitcoin_signature_2: if were_node_one { msg.bitcoin_signature } else { our_bitcoin_sig },
- contents: announcement,
- },
+ msg: try_chan_entry!(self, chan.get_mut().announcement_signatures(&self.our_network_key, self.get_our_node_id(), self.genesis_hash.clone(), msg), channel_state, chan),
update_msg: self.get_channel_update(chan.get()).unwrap(), // can only fail if we're not in a ready state
});
},
#[cfg(any(test, feature = "fuzztarget", feature = "_test_utils"))]
pub fn get_and_clear_pending_events(&self) -> Vec<events::Event> {
- let events = std::cell::RefCell::new(Vec::new());
+ let events = core::cell::RefCell::new(Vec::new());
let event_handler = |event| events.borrow_mut().push(event);
self.process_pending_events(&event_handler);
events.into_inner()
const SERIALIZATION_VERSION: u8 = 1;
const MIN_SERIALIZATION_VERSION: u8 = 1;
-impl Writeable for PendingHTLCInfo {
+impl Writeable for PendingHTLCRouting {
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
- match &self.routing {
+ match &self {
&PendingHTLCRouting::Forward { ref onion_packet, ref short_channel_id } => {
0u8.write(writer)?;
onion_packet.write(writer)?;
incoming_cltv_expiry.write(writer)?;
},
}
- self.incoming_shared_secret.write(writer)?;
- self.payment_hash.write(writer)?;
- self.amt_to_forward.write(writer)?;
- self.outgoing_cltv_value.write(writer)?;
Ok(())
}
}
-impl Readable for PendingHTLCInfo {
- fn read<R: ::std::io::Read>(reader: &mut R) -> Result<PendingHTLCInfo, DecodeError> {
- Ok(PendingHTLCInfo {
- routing: match Readable::read(reader)? {
- 0u8 => PendingHTLCRouting::Forward {
- onion_packet: Readable::read(reader)?,
- short_channel_id: Readable::read(reader)?,
- },
- 1u8 => PendingHTLCRouting::Receive {
- payment_data: msgs::FinalOnionHopData {
- payment_secret: Readable::read(reader)?,
- total_msat: Readable::read(reader)?,
- },
- incoming_cltv_expiry: Readable::read(reader)?,
+impl Readable for PendingHTLCRouting {
+ fn read<R: ::std::io::Read>(reader: &mut R) -> Result<PendingHTLCRouting, DecodeError> {
+ match Readable::read(reader)? {
+ 0u8 => Ok(PendingHTLCRouting::Forward {
+ onion_packet: Readable::read(reader)?,
+ short_channel_id: Readable::read(reader)?,
+ }),
+ 1u8 => Ok(PendingHTLCRouting::Receive {
+ payment_data: msgs::FinalOnionHopData {
+ payment_secret: Readable::read(reader)?,
+ total_msat: Readable::read(reader)?,
},
- _ => return Err(DecodeError::InvalidValue),
- },
- incoming_shared_secret: Readable::read(reader)?,
- payment_hash: Readable::read(reader)?,
- amt_to_forward: Readable::read(reader)?,
- outgoing_cltv_value: Readable::read(reader)?,
- })
+ incoming_cltv_expiry: Readable::read(reader)?,
+ }),
+ _ => Err(DecodeError::InvalidValue),
+ }
}
}
+impl_writeable_tlv_based!(PendingHTLCInfo, {
+ (0, routing),
+ (2, incoming_shared_secret),
+ (4, payment_hash),
+ (6, amt_to_forward),
+ (8, outgoing_cltv_value)
+}, {}, {});
+
impl Writeable for HTLCFailureMsg {
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
match self {
}
}
-impl_writeable!(HTLCPreviousHopData, 0, {
- short_channel_id,
- outpoint,
- htlc_id,
- incoming_packet_shared_secret
-});
+impl_writeable_tlv_based!(HTLCPreviousHopData, {
+ (0, short_channel_id),
+ (2, outpoint),
+ (4, htlc_id),
+ (6, incoming_packet_shared_secret)
+}, {}, {});
impl Writeable for ClaimableHTLC {
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
- self.prev_hop.write(writer)?;
- self.value.write(writer)?;
- self.payment_data.payment_secret.write(writer)?;
- self.payment_data.total_msat.write(writer)?;
- self.cltv_expiry.write(writer)
+ write_tlv_fields!(writer, {
+ (0, self.prev_hop),
+ (2, self.value),
+ (4, self.payment_data.payment_secret),
+ (6, self.payment_data.total_msat),
+ (8, self.cltv_expiry)
+ }, {});
+ Ok(())
}
}
impl Readable for ClaimableHTLC {
fn read<R: ::std::io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
+ let mut prev_hop = HTLCPreviousHopData {
+ short_channel_id: 0, htlc_id: 0,
+ incoming_packet_shared_secret: [0; 32],
+ outpoint: OutPoint::null(),
+ };
+ let mut value = 0;
+ let mut payment_secret = PaymentSecret([0; 32]);
+ let mut total_msat = 0;
+ let mut cltv_expiry = 0;
+ read_tlv_fields!(reader, {
+ (0, prev_hop),
+ (2, value),
+ (4, payment_secret),
+ (6, total_msat),
+ (8, cltv_expiry)
+ }, {});
Ok(ClaimableHTLC {
- prev_hop: Readable::read(reader)?,
- value: Readable::read(reader)?,
+ prev_hop,
+ value,
payment_data: msgs::FinalOnionHopData {
- payment_secret: Readable::read(reader)?,
- total_msat: Readable::read(reader)?,
+ payment_secret,
+ total_msat,
},
- cltv_expiry: Readable::read(reader)?,
+ cltv_expiry,
})
}
}
}
}
-impl_writeable!(PendingInboundPayment, 0, {
- payment_secret,
- expiry_time,
- user_payment_id,
- payment_preimage,
- min_value_msat
-});
+impl_writeable_tlv_based!(PendingInboundPayment, {
+ (0, payment_secret),
+ (2, expiry_time),
+ (4, user_payment_id),
+ (6, payment_preimage),
+ (8, min_value_msat),
+}, {}, {});
impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> Writeable for ChannelManager<Signer, M, T, K, F, L>
where M::Target: chain::Watch<Signer>,
use bitcoin::hashes::sha256::Hash as Sha256;
use bitcoin::{Block, BlockHeader, Transaction, TxOut};
- use std::sync::Mutex;
+ use std::sync::{Arc, Mutex};
use test::Bencher;
let network = bitcoin::Network::Testnet;
let genesis_hash = bitcoin::blockdata::constants::genesis_block(network).header.block_hash();
- let tx_broadcaster = test_utils::TestBroadcaster{txn_broadcasted: Mutex::new(Vec::new())};
+ let tx_broadcaster = test_utils::TestBroadcaster{txn_broadcasted: Mutex::new(Vec::new()), blocks: Arc::new(Mutex::new(Vec::new()))};
let fee_estimator = test_utils::TestFeeEstimator { sat_per_kw: 253 };
let mut config: UserConfig = Default::default();