No flags found
Use flags to group coverage reports by test type, project and/or folders.
Then setup custom commit statuses and notifications for each flag.
e.g., #unittest #integration
#production #enterprise
#frontend #backend
Use flags to group coverage reports by test type, project and/or folders.
Then setup custom commit statuses and notifications for each flag.
e.g., #unittest #integration
#production #enterprise
#frontend #backend
121 | 121 | ||
122 | 122 | impl<C: Deref + Sync + Send, L: Deref + Sync + Send> RoutingMessageHandler for NetGraphMsgHandler<C, L> where C::Target: chain::Access, L::Target: Logger { |
|
123 | 123 | fn handle_node_announcement(&self, msg: &msgs::NodeAnnouncement) -> Result<bool, LightningError> { |
|
124 | - | self.network_graph.write().unwrap().update_node_from_announcement(msg, Some(&self.secp_ctx)) |
|
124 | + | self.network_graph.write().unwrap().update_node_from_announcement(msg, &self.secp_ctx)?; |
|
125 | + | Ok(msg.contents.excess_data.is_empty() && msg.contents.excess_address_data.is_empty()) |
|
125 | 126 | } |
|
126 | 127 | ||
127 | 128 | fn handle_channel_announcement(&self, msg: &msgs::ChannelAnnouncement) -> Result<bool, LightningError> { |
|
128 | - | if msg.contents.node_id_1 == msg.contents.node_id_2 || msg.contents.bitcoin_key_1 == msg.contents.bitcoin_key_2 { |
|
129 | - | return Err(LightningError{err: "Channel announcement node had a channel with itself".to_owned(), action: ErrorAction::IgnoreError}); |
|
130 | - | } |
|
131 | - | ||
132 | - | let utxo_value = match &self.chain_access { |
|
133 | - | &None => { |
|
134 | - | // Tentatively accept, potentially exposing us to DoS attacks |
|
135 | - | None |
|
136 | - | }, |
|
137 | - | &Some(ref chain_access) => { |
|
138 | - | match chain_access.get_utxo(&msg.contents.chain_hash, msg.contents.short_channel_id) { |
|
139 | - | Ok(TxOut { value, script_pubkey }) => { |
|
140 | - | let expected_script = Builder::new().push_opcode(opcodes::all::OP_PUSHNUM_2) |
|
141 | - | .push_slice(&msg.contents.bitcoin_key_1.serialize()) |
|
142 | - | .push_slice(&msg.contents.bitcoin_key_2.serialize()) |
|
143 | - | .push_opcode(opcodes::all::OP_PUSHNUM_2) |
|
144 | - | .push_opcode(opcodes::all::OP_CHECKMULTISIG).into_script().to_v0_p2wsh(); |
|
145 | - | if script_pubkey != expected_script { |
|
146 | - | 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}); |
|
147 | - | } |
|
148 | - | //TODO: Check if value is worth storing, use it to inform routing, and compare it |
|
149 | - | //to the new HTLC max field in channel_update |
|
150 | - | Some(value) |
|
151 | - | }, |
|
152 | - | Err(chain::AccessError::UnknownChain) => { |
|
153 | - | return Err(LightningError{err: format!("Channel announced on an unknown chain ({})", msg.contents.chain_hash.encode().to_hex()), action: ErrorAction::IgnoreError}); |
|
154 | - | }, |
|
155 | - | Err(chain::AccessError::UnknownTx) => { |
|
156 | - | return Err(LightningError{err: "Channel announced without corresponding UTXO entry".to_owned(), action: ErrorAction::IgnoreError}); |
|
157 | - | }, |
|
158 | - | } |
|
159 | - | }, |
|
160 | - | }; |
|
161 | - | let result = self.network_graph.write().unwrap().update_channel_from_announcement(msg, utxo_value, Some(&self.secp_ctx)); |
|
129 | + | self.network_graph.write().unwrap().update_channel_from_announcement(msg, &self.chain_access, &self.secp_ctx)?; |
|
162 | 130 | 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 { "" }); |
|
163 | - | result |
|
131 | + | Ok(msg.contents.excess_data.is_empty()) |
|
164 | 132 | } |
|
165 | 133 | ||
166 | 134 | fn handle_htlc_fail_channel_update(&self, update: &msgs::HTLCFailChannelUpdate) { |
|
167 | 135 | match update { |
|
168 | 136 | &msgs::HTLCFailChannelUpdate::ChannelUpdateMessage { ref msg } => { |
|
169 | - | let _ = self.network_graph.write().unwrap().update_channel(msg, Some(&self.secp_ctx)); |
|
137 | + | let _ = self.network_graph.write().unwrap().update_channel(msg, &self.secp_ctx); |
|
170 | 138 | }, |
|
171 | 139 | &msgs::HTLCFailChannelUpdate::ChannelClosed { short_channel_id, is_permanent } => { |
|
172 | 140 | self.network_graph.write().unwrap().close_channel_from_update(short_channel_id, is_permanent); |
178 | 146 | } |
|
179 | 147 | ||
180 | 148 | fn handle_channel_update(&self, msg: &msgs::ChannelUpdate) -> Result<bool, LightningError> { |
|
181 | - | self.network_graph.write().unwrap().update_channel(msg, Some(&self.secp_ctx)) |
|
149 | + | self.network_graph.write().unwrap().update_channel(msg, &self.secp_ctx)?; |
|
150 | + | Ok(msg.contents.excess_data.is_empty()) |
|
182 | 151 | } |
|
183 | 152 | ||
184 | 153 | fn get_next_channel_announcements(&self, starting_point: u64, batch_amount: u8) -> Vec<(ChannelAnnouncement, Option<ChannelUpdate>, Option<ChannelUpdate>)> { |
562 | 531 | } |
|
563 | 532 | } |
|
564 | 533 | ||
565 | - | /// For an already known node (from channel announcements), update its stored properties from a given node announcement. |
|
534 | + | /// For an already known node (from channel announcements), update its stored properties from a |
|
535 | + | /// given node announcement. |
|
566 | 536 | /// |
|
567 | 537 | /// You probably don't want to call this directly, instead relying on a NetGraphMsgHandler's |
|
568 | 538 | /// RoutingMessageHandler implementation to call it indirectly. This may be useful to accept |
|
569 | - | /// routing messages without checking their signatures. |
|
570 | - | /// |
|
571 | - | /// Announcement signatures are checked here only if Secp256k1 object is provided. |
|
572 | - | pub fn update_node_from_announcement<T: secp256k1::Verification>(&mut self, msg: &msgs::NodeAnnouncement, secp_ctx: Option<&Secp256k1<T>>) -> Result<bool, LightningError> { |
|
573 | - | if let Some(sig_verifier) = secp_ctx { |
|
574 | - | let msg_hash = hash_to_message!(&Sha256dHash::hash(&msg.contents.encode()[..])[..]); |
|
575 | - | secp_verify_sig!(sig_verifier, &msg_hash, &msg.signature, &msg.contents.node_id); |
|
576 | - | } |
|
539 | + | /// routing messages from a source using a protocol other than the lightning P2P protocol. |
|
540 | + | pub fn update_node_from_announcement<T: secp256k1::Verification>(&mut self, msg: &msgs::NodeAnnouncement, secp_ctx: &Secp256k1<T>) -> Result<(), LightningError> { |
|
541 | + | let msg_hash = hash_to_message!(&Sha256dHash::hash(&msg.contents.encode()[..])[..]); |
|
542 | + | secp_verify_sig!(secp_ctx, &msg_hash, &msg.signature, &msg.contents.node_id); |
|
543 | + | self.update_node_from_announcement_intern(&msg.contents, Some(&msg)) |
|
544 | + | } |
|
545 | + | ||
546 | + | /// For an already known node (from channel announcements), update its stored properties from a |
|
547 | + | /// given node announcement without verifying the associated signatures. Because we aren't |
|
548 | + | /// given the associated signatures here we cannot relay the node announcement to any of our |
|
549 | + | /// peers. |
|
550 | + | pub fn update_node_from_unsigned_announcement(&mut self, msg: &msgs::UnsignedNodeAnnouncement) -> Result<(), LightningError> { |
|
551 | + | self.update_node_from_announcement_intern(msg, None) |
|
552 | + | } |
|
577 | 553 | ||
578 | - | match self.nodes.get_mut(&msg.contents.node_id) { |
|
554 | + | fn update_node_from_announcement_intern(&mut self, msg: &msgs::UnsignedNodeAnnouncement, full_msg: Option<&msgs::NodeAnnouncement>) -> Result<(), LightningError> { |
|
555 | + | match self.nodes.get_mut(&msg.node_id) { |
|
579 | 556 | None => Err(LightningError{err: "No existing channels for node_announcement".to_owned(), action: ErrorAction::IgnoreError}), |
|
580 | 557 | Some(node) => { |
|
581 | 558 | if let Some(node_info) = node.announcement_info.as_ref() { |
|
582 | - | if node_info.last_update >= msg.contents.timestamp { |
|
559 | + | if node_info.last_update >= msg.timestamp { |
|
583 | 560 | return Err(LightningError{err: "Update older than last processed update".to_owned(), action: ErrorAction::IgnoreError}); |
|
584 | 561 | } |
|
585 | 562 | } |
|
586 | 563 | ||
587 | - | let should_relay = msg.contents.excess_data.is_empty() && msg.contents.excess_address_data.is_empty(); |
|
564 | + | let should_relay = msg.excess_data.is_empty() && msg.excess_address_data.is_empty(); |
|
588 | 565 | node.announcement_info = Some(NodeAnnouncementInfo { |
|
589 | - | features: msg.contents.features.clone(), |
|
590 | - | last_update: msg.contents.timestamp, |
|
591 | - | rgb: msg.contents.rgb, |
|
592 | - | alias: msg.contents.alias, |
|
593 | - | addresses: msg.contents.addresses.clone(), |
|
594 | - | announcement_message: if should_relay { Some(msg.clone()) } else { None }, |
|
566 | + | features: msg.features.clone(), |
|
567 | + | last_update: msg.timestamp, |
|
568 | + | rgb: msg.rgb, |
|
569 | + | alias: msg.alias, |
|
570 | + | addresses: msg.addresses.clone(), |
|
571 | + | announcement_message: if should_relay { full_msg.cloned() } else { None }, |
|
595 | 572 | }); |
|
596 | 573 | ||
597 | - | Ok(should_relay) |
|
574 | + | Ok(()) |
|
598 | 575 | } |
|
599 | 576 | } |
|
600 | 577 | } |
603 | 580 | /// |
|
604 | 581 | /// You probably don't want to call this directly, instead relying on a NetGraphMsgHandler's |
|
605 | 582 | /// RoutingMessageHandler implementation to call it indirectly. This may be useful to accept |
|
606 | - | /// routing messages without checking their signatures. |
|
583 | + | /// routing messages from a source using a protocol other than the lightning P2P protocol. |
|
607 | 584 | /// |
|
608 | - | /// If the channel has been confirmed to exist on chain (with correctly-formatted scripts on |
|
609 | - | /// chain), set utxo_value to the value of the output on chain, otherwise leave it as None. |
|
610 | - | /// The UTXO value is then used in routing calculation if we have no better information on the |
|
611 | - | /// maximum HTLC value that can be sent over the channel. |
|
612 | - | /// |
|
613 | - | /// Further, setting utxo_value to Some indicates that the announcement message is genuine, |
|
614 | - | /// allowing us to update existing channel data in the case of reorgs or to replace bogus |
|
615 | - | /// channel data generated by a DoS attacker. |
|
585 | + | /// If a `chain::Access` object is provided via `chain_access`, it will be called to verify |
|
586 | + | /// the corresponding UTXO exists on chain and is correctly-formatted. |
|
587 | + | pub fn update_channel_from_announcement<T: secp256k1::Verification, C: Deref> |
|
588 | + | (&mut self, msg: &msgs::ChannelAnnouncement, chain_access: &Option<C>, secp_ctx: &Secp256k1<T>) |
|
589 | + | -> Result<(), LightningError> |
|
590 | + | where C::Target: chain::Access { |
|
591 | + | let msg_hash = hash_to_message!(&Sha256dHash::hash(&msg.contents.encode()[..])[..]); |
|
592 | + | secp_verify_sig!(secp_ctx, &msg_hash, &msg.node_signature_1, &msg.contents.node_id_1); |
|
593 | + | secp_verify_sig!(secp_ctx, &msg_hash, &msg.node_signature_2, &msg.contents.node_id_2); |
|
594 | + | secp_verify_sig!(secp_ctx, &msg_hash, &msg.bitcoin_signature_1, &msg.contents.bitcoin_key_1); |
|
595 | + | secp_verify_sig!(secp_ctx, &msg_hash, &msg.bitcoin_signature_2, &msg.contents.bitcoin_key_2); |
|
596 | + | self.update_channel_from_unsigned_announcement_intern(&msg.contents, Some(msg), chain_access) |
|
597 | + | } |
|
598 | + | ||
599 | + | /// Store or update channel info from a channel announcement without verifying the associated |
|
600 | + | /// signatures. Because we aren't given the associated signatures here we cannot relay the |
|
601 | + | /// channel announcement to any of our peers. |
|
616 | 602 | /// |
|
617 | - | /// Announcement signatures are checked here only if Secp256k1 object is provided. |
|
618 | - | 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> { |
|
619 | - | if msg.contents.node_id_1 == msg.contents.node_id_2 || msg.contents.bitcoin_key_1 == msg.contents.bitcoin_key_2 { |
|
620 | - | return Err(LightningError{err: "Channel announcement node had a channel with itself".to_owned(), action: ErrorAction::IgnoreError}); |
|
621 | - | } |
|
603 | + | /// If a `chain::Access` object is provided via `chain_access`, it will be called to verify |
|
604 | + | /// the corresponding UTXO exists on chain and is correctly-formatted. |
|
605 | + | pub fn update_channel_from_unsigned_announcement<C: Deref> |
|
606 | + | (&mut self, msg: &msgs::UnsignedChannelAnnouncement, chain_access: &Option<C>) |
|
607 | + | -> Result<(), LightningError> |
|
608 | + | where C::Target: chain::Access { |
|
609 | + | self.update_channel_from_unsigned_announcement_intern(msg, None, chain_access) |
|
610 | + | } |
|
622 | 611 | ||
623 | - | if let Some(sig_verifier) = secp_ctx { |
|
624 | - | let msg_hash = hash_to_message!(&Sha256dHash::hash(&msg.contents.encode()[..])[..]); |
|
625 | - | secp_verify_sig!(sig_verifier, &msg_hash, &msg.node_signature_1, &msg.contents.node_id_1); |
|
626 | - | secp_verify_sig!(sig_verifier, &msg_hash, &msg.node_signature_2, &msg.contents.node_id_2); |
|
627 | - | secp_verify_sig!(sig_verifier, &msg_hash, &msg.bitcoin_signature_1, &msg.contents.bitcoin_key_1); |
|
628 | - | secp_verify_sig!(sig_verifier, &msg_hash, &msg.bitcoin_signature_2, &msg.contents.bitcoin_key_2); |
|
612 | + | fn update_channel_from_unsigned_announcement_intern<C: Deref> |
|
613 | + | (&mut self, msg: &msgs::UnsignedChannelAnnouncement, full_msg: Option<&msgs::ChannelAnnouncement>, chain_access: &Option<C>) |
|
614 | + | -> Result<(), LightningError> |
|
615 | + | where C::Target: chain::Access { |
|
616 | + | if msg.node_id_1 == msg.node_id_2 || msg.bitcoin_key_1 == msg.bitcoin_key_2 { |
|
617 | + | return Err(LightningError{err: "Channel announcement node had a channel with itself".to_owned(), action: ErrorAction::IgnoreError}); |
|
629 | 618 | } |
|
630 | 619 | ||
631 | - | let should_relay = msg.contents.excess_data.is_empty(); |
|
620 | + | let utxo_value = match &chain_access { |
|
621 | + | &None => { |
|
622 | + | // Tentatively accept, potentially exposing us to DoS attacks |
|
623 | + | None |
|
624 | + | }, |
|
625 | + | &Some(ref chain_access) => { |
|
626 | + | match chain_access.get_utxo(&msg.chain_hash, msg.short_channel_id) { |
|
627 | + | Ok(TxOut { value, script_pubkey }) => { |
|
628 | + | let expected_script = Builder::new().push_opcode(opcodes::all::OP_PUSHNUM_2) |
|
629 | + | .push_slice(&msg.bitcoin_key_1.serialize()) |
|
630 | + | .push_slice(&msg.bitcoin_key_2.serialize()) |
|
631 | + | .push_opcode(opcodes::all::OP_PUSHNUM_2) |
|
632 | + | .push_opcode(opcodes::all::OP_CHECKMULTISIG).into_script().to_v0_p2wsh(); |
|
633 | + | if script_pubkey != expected_script { |
|
634 | + | 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}); |
|
635 | + | } |
|
636 | + | //TODO: Check if value is worth storing, use it to inform routing, and compare it |
|
637 | + | //to the new HTLC max field in channel_update |
|
638 | + | Some(value) |
|
639 | + | }, |
|
640 | + | Err(chain::AccessError::UnknownChain) => { |
|
641 | + | return Err(LightningError{err: format!("Channel announced on an unknown chain ({})", msg.chain_hash.encode().to_hex()), action: ErrorAction::IgnoreError}); |
|
642 | + | }, |
|
643 | + | Err(chain::AccessError::UnknownTx) => { |
|
644 | + | return Err(LightningError{err: "Channel announced without corresponding UTXO entry".to_owned(), action: ErrorAction::IgnoreError}); |
|
645 | + | }, |
|
646 | + | } |
|
647 | + | }, |
|
648 | + | }; |
|
632 | 649 | ||
633 | 650 | let chan_info = ChannelInfo { |
|
634 | - | features: msg.contents.features.clone(), |
|
635 | - | node_one: msg.contents.node_id_1.clone(), |
|
651 | + | features: msg.features.clone(), |
|
652 | + | node_one: msg.node_id_1.clone(), |
|
636 | 653 | one_to_two: None, |
|
637 | - | node_two: msg.contents.node_id_2.clone(), |
|
654 | + | node_two: msg.node_id_2.clone(), |
|
638 | 655 | two_to_one: None, |
|
639 | 656 | capacity_sats: utxo_value, |
|
640 | - | announcement_message: if should_relay { Some(msg.clone()) } else { None }, |
|
657 | + | announcement_message: if msg.excess_data.is_empty() { full_msg.cloned() } else { None }, |
|
641 | 658 | }; |
|
642 | 659 | ||
643 | - | match self.channels.entry(msg.contents.short_channel_id) { |
|
660 | + | match self.channels.entry(msg.short_channel_id) { |
|
644 | 661 | BtreeEntry::Occupied(mut entry) => { |
|
645 | 662 | //TODO: because asking the blockchain if short_channel_id is valid is only optional |
|
646 | 663 | //in the blockchain API, we need to handle it smartly here, though it's unclear |
654 | 671 | // b) we don't track UTXOs of channels we know about and remove them if they |
|
655 | 672 | // get reorg'd out. |
|
656 | 673 | // c) it's unclear how to do so without exposing ourselves to massive DoS risk. |
|
657 | - | Self::remove_channel_in_nodes(&mut self.nodes, &entry.get(), msg.contents.short_channel_id); |
|
674 | + | Self::remove_channel_in_nodes(&mut self.nodes, &entry.get(), msg.short_channel_id); |
|
658 | 675 | *entry.get_mut() = chan_info; |
|
659 | 676 | } else { |
|
660 | 677 | return Err(LightningError{err: "Already have knowledge of channel".to_owned(), action: ErrorAction::IgnoreError}) |
669 | 686 | ( $node_id: expr ) => { |
|
670 | 687 | match self.nodes.entry($node_id) { |
|
671 | 688 | BtreeEntry::Occupied(node_entry) => { |
|
672 | - | node_entry.into_mut().channels.push(msg.contents.short_channel_id); |
|
689 | + | node_entry.into_mut().channels.push(msg.short_channel_id); |
|
673 | 690 | }, |
|
674 | 691 | BtreeEntry::Vacant(node_entry) => { |
|
675 | 692 | node_entry.insert(NodeInfo { |
|
676 | - | channels: vec!(msg.contents.short_channel_id), |
|
693 | + | channels: vec!(msg.short_channel_id), |
|
677 | 694 | lowest_inbound_channel_fees: None, |
|
678 | 695 | announcement_info: None, |
|
679 | 696 | }); |
682 | 699 | }; |
|
683 | 700 | } |
|
684 | 701 | ||
685 | - | add_channel_to_node!(msg.contents.node_id_1); |
|
686 | - | add_channel_to_node!(msg.contents.node_id_2); |
|
702 | + | add_channel_to_node!(msg.node_id_1); |
|
703 | + | add_channel_to_node!(msg.node_id_2); |
|
687 | 704 | ||
688 | - | Ok(should_relay) |
|
705 | + | Ok(()) |
|
689 | 706 | } |
|
690 | 707 | ||
691 | 708 | /// Close a channel if a corresponding HTLC fail was sent. |
717 | 734 | } |
|
718 | 735 | } |
|
719 | 736 | ||
720 | - | /// For an already known (from announcement) channel, update info about one of the directions of a channel. |
|
737 | + | /// For an already known (from announcement) channel, update info about one of the directions |
|
738 | + | /// of the channel. |
|
721 | 739 | /// |
|
722 | 740 | /// You probably don't want to call this directly, instead relying on a NetGraphMsgHandler's |
|
723 | 741 | /// RoutingMessageHandler implementation to call it indirectly. This may be useful to accept |
|
724 | - | /// routing messages without checking their signatures. |
|
725 | - | /// |
|
726 | - | /// Announcement signatures are checked here only if Secp256k1 object is provided. |
|
727 | - | pub fn update_channel(&mut self, msg: &msgs::ChannelUpdate, secp_ctx: Option<&Secp256k1<secp256k1::VerifyOnly>>) -> Result<bool, LightningError> { |
|
742 | + | /// routing messages from a source using a protocol other than the lightning P2P protocol. |
|
743 | + | pub fn update_channel<T: secp256k1::Verification>(&mut self, msg: &msgs::ChannelUpdate, secp_ctx: &Secp256k1<T>) -> Result<(), LightningError> { |
|
744 | + | self.update_channel_intern(&msg.contents, Some(&msg), Some((&msg.signature, secp_ctx))) |
|
745 | + | } |
|
746 | + | ||
747 | + | /// For an already known (from announcement) channel, update info about one of the directions |
|
748 | + | /// of the channel without verifying the associated signatures. Because we aren't given the |
|
749 | + | /// associated signatures here we cannot relay the channel update to any of our peers. |
|
750 | + | pub fn update_channel_unsigned(&mut self, msg: &msgs::UnsignedChannelUpdate) -> Result<(), LightningError> { |
|
751 | + | self.update_channel_intern(msg, None, None::<(&secp256k1::Signature, &Secp256k1<secp256k1::VerifyOnly>)>) |
|
752 | + | } |
|
753 | + | ||
754 | + | fn update_channel_intern<T: secp256k1::Verification>(&mut self, msg: &msgs::UnsignedChannelUpdate, full_msg: Option<&msgs::ChannelUpdate>, sig_info: Option<(&secp256k1::Signature, &Secp256k1<T>)>) -> Result<(), LightningError> { |
|
728 | 755 | let dest_node_id; |
|
729 | - | let chan_enabled = msg.contents.flags & (1 << 1) != (1 << 1); |
|
756 | + | let chan_enabled = msg.flags & (1 << 1) != (1 << 1); |
|
730 | 757 | let chan_was_enabled; |
|
731 | 758 | ||
732 | - | match self.channels.get_mut(&msg.contents.short_channel_id) { |
|
759 | + | match self.channels.get_mut(&msg.short_channel_id) { |
|
733 | 760 | None => return Err(LightningError{err: "Couldn't find channel for update".to_owned(), action: ErrorAction::IgnoreError}), |
|
734 | 761 | Some(channel) => { |
|
735 | - | if let OptionalField::Present(htlc_maximum_msat) = msg.contents.htlc_maximum_msat { |
|
762 | + | if let OptionalField::Present(htlc_maximum_msat) = msg.htlc_maximum_msat { |
|
736 | 763 | if htlc_maximum_msat > MAX_VALUE_MSAT { |
|
737 | 764 | return Err(LightningError{err: "htlc_maximum_msat is larger than maximum possible msats".to_owned(), action: ErrorAction::IgnoreError}); |
|
738 | 765 | } |
748 | 775 | macro_rules! maybe_update_channel_info { |
|
749 | 776 | ( $target: expr, $src_node: expr) => { |
|
750 | 777 | if let Some(existing_chan_info) = $target.as_ref() { |
|
751 | - | if existing_chan_info.last_update >= msg.contents.timestamp { |
|
778 | + | if existing_chan_info.last_update >= msg.timestamp { |
|
752 | 779 | return Err(LightningError{err: "Update older than last processed update".to_owned(), action: ErrorAction::IgnoreError}); |
|
753 | 780 | } |
|
754 | 781 | chan_was_enabled = existing_chan_info.enabled; |
|
755 | 782 | } else { |
|
756 | 783 | chan_was_enabled = false; |
|
757 | 784 | } |
|
758 | 785 | ||
759 | - | let last_update_message = if msg.contents.excess_data.is_empty() { |
|
760 | - | Some(msg.clone()) |
|
761 | - | } else { |
|
762 | - | None |
|
763 | - | }; |
|
786 | + | let last_update_message = if msg.excess_data.is_empty() { full_msg.cloned() } else { None }; |
|
764 | 787 | ||
765 | 788 | let updated_channel_dir_info = DirectionalChannelInfo { |
|
766 | 789 | enabled: chan_enabled, |
|
767 | - | last_update: msg.contents.timestamp, |
|
768 | - | cltv_expiry_delta: msg.contents.cltv_expiry_delta, |
|
769 | - | htlc_minimum_msat: msg.contents.htlc_minimum_msat, |
|
770 | - | htlc_maximum_msat: if let OptionalField::Present(max_value) = msg.contents.htlc_maximum_msat { Some(max_value) } else { None }, |
|
790 | + | last_update: msg.timestamp, |
|
791 | + | cltv_expiry_delta: msg.cltv_expiry_delta, |
|
792 | + | htlc_minimum_msat: msg.htlc_minimum_msat, |
|
793 | + | htlc_maximum_msat: if let OptionalField::Present(max_value) = msg.htlc_maximum_msat { Some(max_value) } else { None }, |
|
771 | 794 | fees: RoutingFees { |
|
772 | - | base_msat: msg.contents.fee_base_msat, |
|
773 | - | proportional_millionths: msg.contents.fee_proportional_millionths, |
|
795 | + | base_msat: msg.fee_base_msat, |
|
796 | + | proportional_millionths: msg.fee_proportional_millionths, |
|
774 | 797 | }, |
|
775 | 798 | last_update_message |
|
776 | 799 | }; |
|
777 | 800 | $target = Some(updated_channel_dir_info); |
|
778 | 801 | } |
|
779 | 802 | } |
|
780 | 803 | ||
781 | - | let msg_hash = hash_to_message!(&Sha256dHash::hash(&msg.contents.encode()[..])[..]); |
|
782 | - | if msg.contents.flags & 1 == 1 { |
|
804 | + | let msg_hash = hash_to_message!(&Sha256dHash::hash(&msg.encode()[..])[..]); |
|
805 | + | if msg.flags & 1 == 1 { |
|
783 | 806 | dest_node_id = channel.node_one.clone(); |
|
784 | - | if let Some(sig_verifier) = secp_ctx { |
|
785 | - | secp_verify_sig!(sig_verifier, &msg_hash, &msg.signature, &channel.node_two); |
|
807 | + | if let Some((sig, ctx)) = sig_info { |
|
808 | + | secp_verify_sig!(ctx, &msg_hash, &sig, &channel.node_two); |
|
786 | 809 | } |
|
787 | 810 | maybe_update_channel_info!(channel.two_to_one, channel.node_two); |
|
788 | 811 | } else { |
|
789 | 812 | dest_node_id = channel.node_two.clone(); |
|
790 | - | if let Some(sig_verifier) = secp_ctx { |
|
791 | - | secp_verify_sig!(sig_verifier, &msg_hash, &msg.signature, &channel.node_one); |
|
813 | + | if let Some((sig, ctx)) = sig_info { |
|
814 | + | secp_verify_sig!(ctx, &msg_hash, &sig, &channel.node_one); |
|
792 | 815 | } |
|
793 | 816 | maybe_update_channel_info!(channel.one_to_two, channel.node_one); |
|
794 | 817 | } |
797 | 820 | ||
798 | 821 | if chan_enabled { |
|
799 | 822 | let node = self.nodes.get_mut(&dest_node_id).unwrap(); |
|
800 | - | let mut base_msat = msg.contents.fee_base_msat; |
|
801 | - | let mut proportional_millionths = msg.contents.fee_proportional_millionths; |
|
823 | + | let mut base_msat = msg.fee_base_msat; |
|
824 | + | let mut proportional_millionths = msg.fee_proportional_millionths; |
|
802 | 825 | if let Some(fees) = node.lowest_inbound_channel_fees { |
|
803 | 826 | base_msat = cmp::min(base_msat, fees.base_msat); |
|
804 | 827 | proportional_millionths = cmp::min(proportional_millionths, fees.proportional_millionths); |
832 | 855 | node.lowest_inbound_channel_fees = lowest_inbound_channel_fees; |
|
833 | 856 | } |
|
834 | 857 | ||
835 | - | Ok(msg.contents.excess_data.is_empty()) |
|
858 | + | Ok(()) |
|
836 | 859 | } |
|
837 | 860 | ||
838 | 861 | fn remove_channel_in_nodes(nodes: &mut BTreeMap<PublicKey, NodeInfo>, chan: &ChannelInfo, short_channel_id: u64) { |
1178 | 1201 | unsigned_announcement.node_id_1 = PublicKey::from_secret_key(&secp_ctx, node_2_privkey); |
|
1179 | 1202 | msghash = hash_to_message!(&Sha256dHash::hash(&unsigned_announcement.encode()[..])[..]); |
|
1180 | 1203 | let channel_to_itself_announcement = ChannelAnnouncement { |
|
1181 | - | node_signature_1: secp_ctx.sign(&msghash, node_1_privkey), |
|
1182 | - | node_signature_2: secp_ctx.sign(&msghash, node_1_privkey), |
|
1204 | + | node_signature_1: secp_ctx.sign(&msghash, node_2_privkey), |
|
1205 | + | node_signature_2: secp_ctx.sign(&msghash, node_2_privkey), |
|
1183 | 1206 | bitcoin_signature_1: secp_ctx.sign(&msghash, node_1_btckey), |
|
1184 | 1207 | bitcoin_signature_2: secp_ctx.sign(&msghash, node_2_btckey), |
|
1185 | 1208 | contents: unsigned_announcement.clone(), |
Learn more Showing 1 files with coverage changes found.
lightning/src/ln/functional_tests.rs
Files | Coverage |
---|---|
lightning/src | +<.01% 91.41% |
Project Totals (37 files) | 91.41% |
ccd4a7a
3b6f7f1
d9c03f2
9642356
fc7df54