let msg = decode_msg_with_len16!(msgs::ChannelAnnouncement, 64*4, 32+8+33*4);
node_pks.insert(msg.contents.node_id_1);
node_pks.insert(msg.contents.node_id_2);
- let _ = net_graph.update_channel_from_announcement::<secp256k1::VerifyOnly>(&msg, None, None);
+ let _ = net_graph.update_channel_from_announcement::<secp256k1::VerifyOnly, &FuzzChainSource>(&msg, &None, None);
},
2 => {
let msg = decode_msg_with_len16!(msgs::ChannelAnnouncement, 64*4, 32+8+33*4);
node_pks.insert(msg.contents.node_id_1);
node_pks.insert(msg.contents.node_id_2);
- let val = slice_to_be64(get_slice!(8));
- let _ = net_graph.update_channel_from_announcement::<secp256k1::VerifyOnly>(&msg, Some(val), None);
+ let _ = net_graph.update_channel_from_announcement::<secp256k1::VerifyOnly, &FuzzChainSource>(&msg, &Some(&FuzzChainSource { input: Arc::clone(&input) }), None);
},
3 => {
let _ = net_graph.update_channel(&decode_msg!(msgs::ChannelUpdate, 136), None);
}
fn handle_channel_announcement(&self, msg: &msgs::ChannelAnnouncement) -> Result<bool, LightningError> {
- if msg.contents.node_id_1 == msg.contents.node_id_2 || msg.contents.bitcoin_key_1 == msg.contents.bitcoin_key_2 {
- return Err(LightningError{err: "Channel announcement node had a channel with itself".to_owned(), action: ErrorAction::IgnoreError});
- }
-
- let utxo_value = match &self.chain_access {
- &None => {
- // Tentatively accept, potentially exposing us to DoS attacks
- None
- },
- &Some(ref chain_access) => {
- match chain_access.get_utxo(&msg.contents.chain_hash, msg.contents.short_channel_id) {
- Ok(TxOut { value, script_pubkey }) => {
- let expected_script = Builder::new().push_opcode(opcodes::all::OP_PUSHNUM_2)
- .push_slice(&msg.contents.bitcoin_key_1.serialize())
- .push_slice(&msg.contents.bitcoin_key_2.serialize())
- .push_opcode(opcodes::all::OP_PUSHNUM_2)
- .push_opcode(opcodes::all::OP_CHECKMULTISIG).into_script().to_v0_p2wsh();
- if script_pubkey != expected_script {
- return Err(LightningError{err: format!("Channel announcement key ({}) didn't match on-chain script ({})", script_pubkey.to_hex(), expected_script.to_hex()), action: ErrorAction::IgnoreError});
- }
- //TODO: Check if value is worth storing, use it to inform routing, and compare it
- //to the new HTLC max field in channel_update
- Some(value)
- },
- Err(chain::AccessError::UnknownChain) => {
- return Err(LightningError{err: format!("Channel announced on an unknown chain ({})", msg.contents.chain_hash.encode().to_hex()), action: ErrorAction::IgnoreError});
- },
- Err(chain::AccessError::UnknownTx) => {
- return Err(LightningError{err: "Channel announced without corresponding UTXO entry".to_owned(), action: ErrorAction::IgnoreError});
- },
- }
- },
- };
- let result = self.network_graph.write().unwrap().update_channel_from_announcement(msg, utxo_value, Some(&self.secp_ctx));
+ let result = self.network_graph.write().unwrap().update_channel_from_announcement(msg, &self.chain_access, Some(&self.secp_ctx));
log_trace!(self.logger, "Added channel_announcement for {}{}", msg.contents.short_channel_id, if !msg.contents.excess_data.is_empty() { " with excess uninterpreted data!" } else { "" });
result
}
/// RoutingMessageHandler implementation to call it indirectly. This may be useful to accept
/// routing messages without checking their signatures.
///
- /// If the channel has been confirmed to exist on chain (with correctly-formatted scripts on
- /// chain), set utxo_value to the value of the output on chain, otherwise leave it as None.
- /// The UTXO value is then used in routing calculation if we have no better information on the
- /// maximum HTLC value that can be sent over the channel.
- ///
- /// Further, setting utxo_value to Some indicates that the announcement message is genuine,
- /// allowing us to update existing channel data in the case of reorgs or to replace bogus
- /// channel data generated by a DoS attacker.
+ /// If a `chain::Access` object is provided via `chain_access`, it will be called to verify
+ /// the corresponding UTXO exists on chain and is correctly-formatted.
///
/// Announcement signatures are checked here only if Secp256k1 object is provided.
- pub fn update_channel_from_announcement<T: secp256k1::Verification>(&mut self, msg: &msgs::ChannelAnnouncement, utxo_value: Option<u64>, secp_ctx: Option<&Secp256k1<T>>) -> Result<bool, LightningError> {
+ pub fn update_channel_from_announcement<T: secp256k1::Verification, C: Deref>
+ (&mut self, msg: &msgs::ChannelAnnouncement, chain_access: &Option<C>, secp_ctx: Option<&Secp256k1<T>>)
+ -> Result<bool, LightningError>
+ where C::Target: chain::Access {
if msg.contents.node_id_1 == msg.contents.node_id_2 || msg.contents.bitcoin_key_1 == msg.contents.bitcoin_key_2 {
return Err(LightningError{err: "Channel announcement node had a channel with itself".to_owned(), action: ErrorAction::IgnoreError});
}
secp_verify_sig!(sig_verifier, &msg_hash, &msg.bitcoin_signature_2, &msg.contents.bitcoin_key_2);
}
- let should_relay = msg.contents.excess_data.is_empty();
+ let utxo_value = match &chain_access {
+ &None => {
+ // Tentatively accept, potentially exposing us to DoS attacks
+ None
+ },
+ &Some(ref chain_access) => {
+ match chain_access.get_utxo(&msg.contents.chain_hash, msg.contents.short_channel_id) {
+ Ok(TxOut { value, script_pubkey }) => {
+ let expected_script = Builder::new().push_opcode(opcodes::all::OP_PUSHNUM_2)
+ .push_slice(&msg.contents.bitcoin_key_1.serialize())
+ .push_slice(&msg.contents.bitcoin_key_2.serialize())
+ .push_opcode(opcodes::all::OP_PUSHNUM_2)
+ .push_opcode(opcodes::all::OP_CHECKMULTISIG).into_script().to_v0_p2wsh();
+ if script_pubkey != expected_script {
+ return Err(LightningError{err: format!("Channel announcement key ({}) didn't match on-chain script ({})", script_pubkey.to_hex(), expected_script.to_hex()), action: ErrorAction::IgnoreError});
+ }
+ //TODO: Check if value is worth storing, use it to inform routing, and compare it
+ //to the new HTLC max field in channel_update
+ Some(value)
+ },
+ Err(chain::AccessError::UnknownChain) => {
+ return Err(LightningError{err: format!("Channel announced on an unknown chain ({})", msg.contents.chain_hash.encode().to_hex()), action: ErrorAction::IgnoreError});
+ },
+ Err(chain::AccessError::UnknownTx) => {
+ return Err(LightningError{err: "Channel announced without corresponding UTXO entry".to_owned(), action: ErrorAction::IgnoreError});
+ },
+ }
+ },
+ };
+ let should_relay = msg.contents.excess_data.is_empty();
let chan_info = ChannelInfo {
features: msg.contents.features.clone(),
node_one: msg.contents.node_id_1.clone(),