false
}
}
+
+ /// Used to broadcast forward gossip messages which were validated async.
+ ///
+ /// Note that this will ignore events other than `Broadcast*` or messages with too much excess
+ /// data.
+ pub(super) fn forward_gossip_msg(&self, mut ev: MessageSendEvent) {
+ match &mut ev {
+ MessageSendEvent::BroadcastChannelAnnouncement { msg, ref mut update_msg } => {
+ if msg.contents.excess_data.len() > MAX_EXCESS_BYTES_FOR_RELAY { return; }
+ if update_msg.as_ref()
+ .map(|msg| msg.contents.excess_data.len()).unwrap_or(0) > MAX_EXCESS_BYTES_FOR_RELAY
+ {
+ *update_msg = None;
+ }
+ },
+ MessageSendEvent::BroadcastChannelUpdate { msg } => {
+ if msg.contents.excess_data.len() > MAX_EXCESS_BYTES_FOR_RELAY { return; }
+ },
+ MessageSendEvent::BroadcastNodeAnnouncement { msg } => {
+ if msg.contents.excess_data.len() > MAX_EXCESS_BYTES_FOR_RELAY ||
+ msg.contents.excess_address_data.len() > MAX_EXCESS_BYTES_FOR_RELAY ||
+ msg.contents.excess_data.len() + msg.contents.excess_address_data.len() > MAX_EXCESS_BYTES_FOR_RELAY
+ {
+ return;
+ }
+ },
+ _ => return,
+ }
+ self.pending_events.lock().unwrap().push(ev);
+ }
}
impl<L: Deref> NetworkGraph<L> where L::Target: Logger {
features.set_gossip_queries_optional();
features
}
+
+ fn processing_queue_high(&self) -> bool {
+ self.network_graph.pending_checks.too_many_checks_pending()
+ }
}
impl<G: Deref<Target=NetworkGraph<L>>, U: Deref, L: Deref> MessageSendEventsProvider for P2PGossipSync<G, U, L>
}
fn update_node_from_announcement_intern(&self, msg: &msgs::UnsignedNodeAnnouncement, full_msg: Option<&msgs::NodeAnnouncement>) -> Result<(), LightningError> {
- match self.nodes.write().unwrap().get_mut(&msg.node_id) {
- None => Err(LightningError{err: "No existing channels for node_announcement".to_owned(), action: ErrorAction::IgnoreError}),
+ let mut nodes = self.nodes.write().unwrap();
+ match nodes.get_mut(&msg.node_id) {
+ None => {
+ core::mem::drop(nodes);
+ self.pending_checks.check_hold_pending_node_announcement(msg, full_msg)?;
+ Err(LightningError{err: "No existing channels for node_announcement".to_owned(), action: ErrorAction::IgnoreError})
+ },
Some(node) => {
if let Some(node_info) = node.announcement_info.as_ref() {
// The timestamp field is somewhat of a misnomer - the BOLTs use it to order
let mut channels = self.channels.write().unwrap();
match channels.get_mut(&msg.short_channel_id) {
- None => return Err(LightningError{err: "Couldn't find channel for update".to_owned(), action: ErrorAction::IgnoreError}),
+ None => {
+ core::mem::drop(channels);
+ self.pending_checks.check_hold_pending_channel_update(msg, full_msg)?;
+ return Err(LightningError{err: "Couldn't find channel for update".to_owned(), action: ErrorAction::IgnoreError});
+ },
Some(channel) => {
if msg.htlc_maximum_msat > MAX_VALUE_MSAT {
return Err(LightningError{err:
}
#[cfg(test)]
-mod tests {
+pub(crate) mod tests {
use crate::ln::channelmanager;
use crate::ln::chan_utils::make_funding_redeemscript;
#[cfg(feature = "std")]
use crate::ln::features::InitFeatures;
use crate::routing::gossip::{P2PGossipSync, NetworkGraph, NetworkUpdate, NodeAlias, MAX_EXCESS_BYTES_FOR_RELAY, NodeId, RoutingFees, ChannelUpdateInfo, ChannelInfo, NodeAnnouncementInfo, NodeInfo};
- use crate::routing::utxo::UtxoLookupError;
+ use crate::routing::utxo::{UtxoLookupError, UtxoResult};
use crate::ln::msgs::{RoutingMessageHandler, UnsignedNodeAnnouncement, NodeAnnouncement,
UnsignedChannelAnnouncement, ChannelAnnouncement, UnsignedChannelUpdate, ChannelUpdate,
ReplyChannelRange, QueryChannelRange, QueryShortChannelIds, MAX_VALUE_MSAT};
assert!(!gossip_sync.should_request_full_sync(&node_id));
}
- fn get_signed_node_announcement<F: Fn(&mut UnsignedNodeAnnouncement)>(f: F, node_key: &SecretKey, secp_ctx: &Secp256k1<secp256k1::All>) -> NodeAnnouncement {
+ pub(crate) fn get_signed_node_announcement<F: Fn(&mut UnsignedNodeAnnouncement)>(f: F, node_key: &SecretKey, secp_ctx: &Secp256k1<secp256k1::All>) -> NodeAnnouncement {
let node_id = NodeId::from_pubkey(&PublicKey::from_secret_key(&secp_ctx, node_key));
let mut unsigned_announcement = UnsignedNodeAnnouncement {
features: channelmanager::provided_node_features(&UserConfig::default()),
}
}
- fn get_signed_channel_announcement<F: Fn(&mut UnsignedChannelAnnouncement)>(f: F, node_1_key: &SecretKey, node_2_key: &SecretKey, secp_ctx: &Secp256k1<secp256k1::All>) -> ChannelAnnouncement {
+ pub(crate) fn get_signed_channel_announcement<F: Fn(&mut UnsignedChannelAnnouncement)>(f: F, node_1_key: &SecretKey, node_2_key: &SecretKey, secp_ctx: &Secp256k1<secp256k1::All>) -> ChannelAnnouncement {
let node_id_1 = PublicKey::from_secret_key(&secp_ctx, node_1_key);
let node_id_2 = PublicKey::from_secret_key(&secp_ctx, node_2_key);
let node_1_btckey = &SecretKey::from_slice(&[40; 32]).unwrap();
}
}
- fn get_channel_script(secp_ctx: &Secp256k1<secp256k1::All>) -> Script {
+ pub(crate) fn get_channel_script(secp_ctx: &Secp256k1<secp256k1::All>) -> Script {
let node_1_btckey = SecretKey::from_slice(&[40; 32]).unwrap();
let node_2_btckey = SecretKey::from_slice(&[39; 32]).unwrap();
make_funding_redeemscript(&PublicKey::from_secret_key(secp_ctx, &node_1_btckey),
&PublicKey::from_secret_key(secp_ctx, &node_2_btckey)).to_v0_p2wsh()
}
- fn get_signed_channel_update<F: Fn(&mut UnsignedChannelUpdate)>(f: F, node_key: &SecretKey, secp_ctx: &Secp256k1<secp256k1::All>) -> ChannelUpdate {
+ pub(crate) fn get_signed_channel_update<F: Fn(&mut UnsignedChannelUpdate)>(f: F, node_key: &SecretKey, secp_ctx: &Secp256k1<secp256k1::All>) -> ChannelUpdate {
let mut unsigned_channel_update = UnsignedChannelUpdate {
chain_hash: genesis_block(Network::Testnet).header.block_hash(),
short_channel_id: 0,
// Test if an associated transaction were not on-chain (or not confirmed).
let chain_source = test_utils::TestChainSource::new(Network::Testnet);
- *chain_source.utxo_ret.lock().unwrap() = Err(UtxoLookupError::UnknownTx);
+ *chain_source.utxo_ret.lock().unwrap() = UtxoResult::Sync(Err(UtxoLookupError::UnknownTx));
let network_graph = NetworkGraph::new(genesis_hash, &logger);
gossip_sync = P2PGossipSync::new(&network_graph, Some(&chain_source), &logger);
};
// Now test if the transaction is found in the UTXO set and the script is correct.
- *chain_source.utxo_ret.lock().unwrap() = Ok(TxOut { value: 0, script_pubkey: good_script.clone() });
+ *chain_source.utxo_ret.lock().unwrap() =
+ UtxoResult::Sync(Ok(TxOut { value: 0, script_pubkey: good_script.clone() }));
let valid_announcement = get_signed_channel_announcement(|unsigned_announcement| {
unsigned_announcement.short_channel_id += 2;
}, node_1_privkey, node_2_privkey, &secp_ctx);
// If we receive announcement for the same channel, once we've validated it against the
// chain, we simply ignore all new (duplicate) announcements.
- *chain_source.utxo_ret.lock().unwrap() = Ok(TxOut { value: 0, script_pubkey: good_script });
+ *chain_source.utxo_ret.lock().unwrap() =
+ UtxoResult::Sync(Ok(TxOut { value: 0, script_pubkey: good_script }));
match gossip_sync.handle_channel_announcement(&valid_announcement) {
Ok(_) => panic!(),
Err(e) => assert_eq!(e.err, "Already have chain-validated channel")
{
// Announce a channel we will update
let good_script = get_channel_script(&secp_ctx);
- *chain_source.utxo_ret.lock().unwrap() = Ok(TxOut { value: amount_sats, script_pubkey: good_script.clone() });
+ *chain_source.utxo_ret.lock().unwrap() =
+ UtxoResult::Sync(Ok(TxOut { value: amount_sats, script_pubkey: good_script.clone() }));
let valid_channel_announcement = get_signed_channel_announcement(|_| {}, node_1_privkey, node_2_privkey, &secp_ctx);
short_channel_id = valid_channel_announcement.contents.short_channel_id;