Merge pull request #457 from ariard/2020-01-fix-append-onchain
authorMatt Corallo <649246+TheBlueMatt@users.noreply.github.com>
Wed, 22 Jan 2020 20:57:36 +0000 (20:57 +0000)
committerGitHub <noreply@github.com>
Wed, 22 Jan 2020 20:57:36 +0000 (20:57 +0000)
Fix spurious calls of broadcast_by_local_state

20 files changed:
.gitignore
fuzz/src/chanmon_consistency.rs
fuzz/src/full_stack.rs
fuzz/src/router.rs
lightning/src/chain/keysinterface.rs
lightning/src/ln/chan_utils.rs
lightning/src/ln/chanmon_update_fail_tests.rs
lightning/src/ln/channel.rs
lightning/src/ln/channelmanager.rs
lightning/src/ln/channelmonitor.rs
lightning/src/ln/features.rs
lightning/src/ln/functional_test_utils.rs
lightning/src/ln/functional_tests.rs
lightning/src/ln/msgs.rs
lightning/src/ln/onion_utils.rs
lightning/src/ln/peer_handler.rs
lightning/src/ln/router.rs
lightning/src/util/enforcing_trait_impls.rs
lightning/src/util/macro_logger.rs
lightning/src/util/test_utils.rs

index c795d9b53373103e2a75b2acfdcb1c27facb24e7..19ed4bd115a78efd45966f8fe9c144e421ca1b06 100644 (file)
@@ -1,4 +1,5 @@
 /target/
+/hfuzz_target/
 /net-tokio/target/
 **/*.rs.bk
 Cargo.lock
index d4a33427ef4b9a1b0eee8483d8f8d5b5e669bf2b..adc00ed8d8eef01439ce7db27980e537621f12d1 100644 (file)
@@ -29,8 +29,8 @@ use lightning::ln::channelmonitor;
 use lightning::ln::channelmonitor::{ChannelMonitor, ChannelMonitorUpdateErr, HTLCUpdate};
 use lightning::ln::channelmanager::{ChannelManager, PaymentHash, PaymentPreimage, ChannelManagerReadArgs};
 use lightning::ln::router::{Route, RouteHop};
-use lightning::ln::features::InitFeatures;
-use lightning::ln::msgs::{CommitmentUpdate, ChannelMessageHandler, ErrorAction, UpdateAddHTLC};
+use lightning::ln::features::{ChannelFeatures, InitFeatures, NodeFeatures};
+use lightning::ln::msgs::{CommitmentUpdate, ChannelMessageHandler, ErrorAction, UpdateAddHTLC, Init};
 use lightning::util::enforcing_trait_impls::EnforcingChannelKeys;
 use lightning::util::events;
 use lightning::util::logger::Logger;
@@ -158,7 +158,7 @@ impl KeysInterface for KeyProvider {
                        delayed_payment_base_key:  SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, self.node_id]).unwrap(),
                        htlc_base_key:             SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, self.node_id]).unwrap(),
                        commitment_seed: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, self.node_id],
-                       remote_funding_pubkey: None,
+                       remote_channel_pubkeys: None,
                })
        }
 
@@ -414,7 +414,9 @@ pub fn do_test(data: &[u8]) {
                                if let Err(_) = $source.send_payment(Route {
                                        hops: vec![RouteHop {
                                                pubkey: $dest.0.get_our_node_id(),
+                                               node_features: NodeFeatures::empty(),
                                                short_channel_id: $dest.1,
+                                               channel_features: ChannelFeatures::empty(),
                                                fee_msat: 5000000,
                                                cltv_expiry_delta: 200,
                                        }],
@@ -429,12 +431,16 @@ pub fn do_test(data: &[u8]) {
                                if let Err(_) = $source.send_payment(Route {
                                        hops: vec![RouteHop {
                                                pubkey: $middle.0.get_our_node_id(),
+                                               node_features: NodeFeatures::empty(),
                                                short_channel_id: $middle.1,
+                                               channel_features: ChannelFeatures::empty(),
                                                fee_msat: 50000,
                                                cltv_expiry_delta: 100,
                                        },RouteHop {
                                                pubkey: $dest.0.get_our_node_id(),
+                                               node_features: NodeFeatures::empty(),
                                                short_channel_id: $dest.1,
+                                               channel_features: ChannelFeatures::empty(),
                                                fee_msat: 5000000,
                                                cltv_expiry_delta: 200,
                                        }],
@@ -650,15 +656,15 @@ pub fn do_test(data: &[u8]) {
                        },
                        0x11 => {
                                if chan_a_disconnected {
-                                       nodes[0].peer_connected(&nodes[1].get_our_node_id());
-                                       nodes[1].peer_connected(&nodes[0].get_our_node_id());
+                                       nodes[0].peer_connected(&nodes[1].get_our_node_id(), &Init { features: InitFeatures::empty() });
+                                       nodes[1].peer_connected(&nodes[0].get_our_node_id(), &Init { features: InitFeatures::empty() });
                                        chan_a_disconnected = false;
                                }
                        },
                        0x12 => {
                                if chan_b_disconnected {
-                                       nodes[1].peer_connected(&nodes[2].get_our_node_id());
-                                       nodes[2].peer_connected(&nodes[1].get_our_node_id());
+                                       nodes[1].peer_connected(&nodes[2].get_our_node_id(), &Init { features: InitFeatures::empty() });
+                                       nodes[2].peer_connected(&nodes[1].get_our_node_id(), &Init { features: InitFeatures::empty() });
                                        chan_b_disconnected = false;
                                }
                        },
index 7e6135b5c658aeba7ee179af755c4ef80234677f..cd855f363fe1c6c4c6bda312a81dadf22a6ca5cf 100644 (file)
@@ -196,10 +196,10 @@ impl<'a> MoneyLossDetector<'a> {
 
        fn disconnect_block(&mut self) {
                if self.height > 0 && (self.max_height < 6 || self.height >= self.max_height - 6) {
-                       self.height -= 1;
                        let header = BlockHeader { version: 0x20000000, prev_blockhash: self.header_hashes[self.height], merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
                        self.manager.block_disconnected(&header, self.height as u32);
                        self.monitor.block_disconnected(&header, self.height as u32);
+                       self.height -= 1;
                        let removal_height = self.height;
                        self.txids_confirmed.retain(|_, height| {
                                removal_height != *height
@@ -257,7 +257,7 @@ impl KeysInterface for KeyProvider {
                                delayed_payment_base_key:  SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, ctr]).unwrap(),
                                htlc_base_key:             SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, ctr]).unwrap(),
                                commitment_seed: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, ctr],
-                               remote_funding_pubkey: None,
+                               remote_channel_pubkeys: None,
                        }
                } else {
                        InMemoryChannelKeys {
@@ -267,7 +267,7 @@ impl KeysInterface for KeyProvider {
                                delayed_payment_base_key:  SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, ctr]).unwrap(),
                                htlc_base_key:             SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, ctr]).unwrap(),
                                commitment_seed: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, ctr],
-                               remote_funding_pubkey: None,
+                               remote_channel_pubkeys: None,
                        }
                })
        }
index 3e8082e47985d3a78175cb17a9f877fe32ae3e60..fbb629220112a63f543135c1be2537908c6ad017 100644 (file)
@@ -5,8 +5,9 @@ use bitcoin::blockdata::transaction::Transaction;
 
 use lightning::chain::chaininterface::{ChainError,ChainWatchInterface};
 use lightning::ln::channelmanager::ChannelDetails;
+use lightning::ln::features::InitFeatures;
 use lightning::ln::msgs;
-use lightning::ln::msgs::{RoutingMessageHandler};
+use lightning::ln::msgs::RoutingMessageHandler;
 use lightning::ln::router::{Router, RouteHint};
 use lightning::util::logger::Logger;
 use lightning::util::ser::Readable;
@@ -198,6 +199,7 @@ pub fn do_test(data: &[u8]) {
                                                                channel_id: [0; 32],
                                                                short_channel_id: Some(slice_to_be64(get_slice!(8))),
                                                                remote_network_id: get_pubkey!(),
+                                                               counterparty_features: InitFeatures::empty(),
                                                                channel_value_satoshis: slice_to_be64(get_slice!(8)),
                                                                user_id: 0,
                                                                inbound_capacity_msat: 0,
index c001646263fdf0d7ae4e1f1c079ed02ab3b40135..689a16603743e228ffff64dfba9ea710474fdc43 100644 (file)
@@ -24,7 +24,7 @@ use util::logger::Logger;
 use util::ser::Writeable;
 
 use ln::chan_utils;
-use ln::chan_utils::{TxCreationKeys, HTLCOutputInCommitment, make_funding_redeemscript};
+use ln::chan_utils::{TxCreationKeys, HTLCOutputInCommitment, make_funding_redeemscript, ChannelPublicKeys};
 use ln::msgs;
 
 use std::sync::Arc;
@@ -142,7 +142,7 @@ pub trait ChannelKeys : Send {
        /// TODO: Document the things someone using this interface should enforce before signing.
        /// TODO: Add more input vars to enable better checking (preferably removing commitment_tx and
        /// making the callee generate it via some util function we expose)!
-       fn sign_remote_commitment<T: secp256k1::Signing>(&self, channel_value_satoshis: u64, feerate_per_kw: u64, commitment_tx: &Transaction, keys: &TxCreationKeys, htlcs: &[&HTLCOutputInCommitment], to_self_delay: u16, secp_ctx: &Secp256k1<T>) -> Result<(Signature, Vec<Signature>), ()>;
+       fn sign_remote_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, channel_value_satoshis: u64, feerate_per_kw: u64, commitment_tx: &Transaction, keys: &TxCreationKeys, htlcs: &[&HTLCOutputInCommitment], to_self_delay: u16, secp_ctx: &Secp256k1<T>) -> Result<(Signature, Vec<Signature>), ()>;
 
        /// Create a signature for a (proposed) closing transaction.
        ///
@@ -158,11 +158,11 @@ pub trait ChannelKeys : Send {
        /// protocol.
        fn sign_channel_announcement<T: secp256k1::Signing>(&self, msg: &msgs::UnsignedChannelAnnouncement, secp_ctx: &Secp256k1<T>) -> Result<Signature, ()>;
 
-       /// Set the remote funding key.  This is done immediately on incoming channels
+       /// Set the remote channel basepoints.  This is done immediately on incoming channels
        /// and as soon as the channel is accepted on outgoing channels.
        ///
        /// Will be called before any signatures are applied.
-       fn set_remote_funding_pubkey(&mut self, key: &PublicKey);
+       fn set_remote_channel_pubkeys(&mut self, channel_points: &ChannelPublicKeys);
 }
 
 #[derive(Clone)]
@@ -181,7 +181,7 @@ pub struct InMemoryChannelKeys {
        /// Commitment seed
        pub commitment_seed: [u8; 32],
        /// Remote funding pubkey
-       pub remote_funding_pubkey: Option<PublicKey>,
+       pub remote_channel_pubkeys: Option<ChannelPublicKeys>,
 }
 
 impl ChannelKeys for InMemoryChannelKeys {
@@ -192,12 +192,12 @@ impl ChannelKeys for InMemoryChannelKeys {
        fn htlc_base_key(&self) -> &SecretKey { &self.htlc_base_key }
        fn commitment_seed(&self) -> &[u8; 32] { &self.commitment_seed }
 
-       fn sign_remote_commitment<T: secp256k1::Signing>(&self, channel_value_satoshis: u64, feerate_per_kw: u64, commitment_tx: &Transaction, keys: &TxCreationKeys, htlcs: &[&HTLCOutputInCommitment], to_self_delay: u16, secp_ctx: &Secp256k1<T>) -> Result<(Signature, Vec<Signature>), ()> {
+       fn sign_remote_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, channel_value_satoshis: u64, feerate_per_kw: u64, commitment_tx: &Transaction, keys: &TxCreationKeys, htlcs: &[&HTLCOutputInCommitment], to_self_delay: u16, secp_ctx: &Secp256k1<T>) -> Result<(Signature, Vec<Signature>), ()> {
                if commitment_tx.input.len() != 1 { return Err(()); }
 
                let funding_pubkey = PublicKey::from_secret_key(secp_ctx, &self.funding_key);
-               let remote_funding_pubkey = self.remote_funding_pubkey.as_ref().expect("must set remote funding key before signing");
-               let channel_funding_redeemscript = make_funding_redeemscript(&funding_pubkey, remote_funding_pubkey);
+               let remote_channel_pubkeys = self.remote_channel_pubkeys.as_ref().expect("must set remote channel pubkeys before signing");
+               let channel_funding_redeemscript = make_funding_redeemscript(&funding_pubkey, &remote_channel_pubkeys.funding_pubkey);
 
                let commitment_sighash = hash_to_message!(&bip143::SighashComponents::new(&commitment_tx).sighash_all(&commitment_tx.input[0], &channel_funding_redeemscript, channel_value_satoshis)[..]);
                let commitment_sig = secp_ctx.sign(&commitment_sighash, &self.funding_key);
@@ -236,9 +236,9 @@ impl ChannelKeys for InMemoryChannelKeys {
                Ok(secp_ctx.sign(&msghash, &self.funding_key))
        }
 
-       fn set_remote_funding_pubkey(&mut self, key: &PublicKey) {
-               assert!(self.remote_funding_pubkey.is_none(), "Already set remote funding key");
-               self.remote_funding_pubkey = Some(*key);
+       fn set_remote_channel_pubkeys(&mut self, channel_pubkeys: &ChannelPublicKeys) {
+               assert!(self.remote_channel_pubkeys.is_none(), "Already set remote channel pubkeys");
+               self.remote_channel_pubkeys = Some(channel_pubkeys.clone());
        }
 }
 
@@ -249,7 +249,7 @@ impl_writeable!(InMemoryChannelKeys, 0, {
        delayed_payment_base_key,
        htlc_base_key,
        commitment_seed,
-       remote_funding_pubkey
+       remote_channel_pubkeys
 });
 
 /// Simple KeysInterface implementor that takes a 32-byte seed for use as a BIP 32 extended key
@@ -398,7 +398,7 @@ impl KeysInterface for KeysManager {
                        delayed_payment_base_key,
                        htlc_base_key,
                        commitment_seed,
-                       remote_funding_pubkey: None,
+                       remote_channel_pubkeys: None,
                }
        }
 
index 19a07aaa19c2ea2c30f5498aee3c32278f7cb0c2..51a2c4b042224464eacbfe5781c9ed36325b992e 100644 (file)
@@ -18,13 +18,32 @@ use ln::channelmanager::{PaymentHash, PaymentPreimage};
 use ln::msgs::DecodeError;
 use util::ser::{Readable, Writeable, Writer, WriterWriteAdaptor};
 
-use secp256k1::key::{SecretKey,PublicKey};
+use secp256k1::key::{SecretKey, PublicKey};
 use secp256k1::{Secp256k1, Signature};
 use secp256k1;
 
 pub(super) const HTLC_SUCCESS_TX_WEIGHT: u64 = 703;
 pub(super) const HTLC_TIMEOUT_TX_WEIGHT: u64 = 663;
 
+#[derive(PartialEq)]
+pub(crate) enum HTLCType {
+       AcceptedHTLC,
+       OfferedHTLC
+}
+
+impl HTLCType {
+       /// Check if a given tx witnessScript len matchs one of a pre-signed HTLC
+       pub(crate) fn scriptlen_to_htlctype(witness_script_len: usize) ->  Option<HTLCType> {
+               if witness_script_len == 133 {
+                       Some(HTLCType::OfferedHTLC)
+               } else if witness_script_len >= 136 && witness_script_len <= 139 {
+                       Some(HTLCType::AcceptedHTLC)
+               } else {
+                       None
+               }
+       }
+}
+
 // Various functions for key derivation and transaction creation for use within channels. Primarily
 // used in Channel and ChannelMonitor.
 
@@ -118,24 +137,57 @@ pub(super) fn derive_public_revocation_key<T: secp256k1::Verification>(secp_ctx:
 
 /// The set of public keys which are used in the creation of one commitment transaction.
 /// These are derived from the channel base keys and per-commitment data.
+#[derive(PartialEq)]
 pub struct TxCreationKeys {
        /// The per-commitment public key which was used to derive the other keys.
        pub per_commitment_point: PublicKey,
        /// The revocation key which is used to allow the owner of the commitment transaction to
        /// provide their counterparty the ability to punish them if they broadcast an old state.
-       pub revocation_key: PublicKey,
+       pub(crate) revocation_key: PublicKey,
        /// A's HTLC Key
-       pub a_htlc_key: PublicKey,
+       pub(crate) a_htlc_key: PublicKey,
        /// B's HTLC Key
-       pub b_htlc_key: PublicKey,
+       pub(crate) b_htlc_key: PublicKey,
        /// A's Payment Key (which isn't allowed to be spent from for some delay)
-       pub a_delayed_payment_key: PublicKey,
+       pub(crate) a_delayed_payment_key: PublicKey,
        /// B's Payment Key
-       pub b_payment_key: PublicKey,
+       pub(crate) b_payment_key: PublicKey,
+}
+
+/// One counterparty's public keys which do not change over the life of a channel.
+#[derive(Clone)]
+pub struct ChannelPublicKeys {
+       /// The public key which is used to sign all commitment transactions, as it appears in the
+       /// on-chain channel lock-in 2-of-2 multisig output.
+       pub funding_pubkey: PublicKey,
+       /// The base point which is used (with derive_public_revocation_key) to derive per-commitment
+       /// revocation keys. The per-commitment revocation private key is then revealed by the owner of
+       /// a commitment transaction so that their counterparty can claim all available funds if they
+       /// broadcast an old state.
+       pub revocation_basepoint: PublicKey,
+       /// The base point which is used (with derive_public_key) to derive a per-commitment payment
+       /// public key which receives immediately-spendable non-HTLC-encumbered funds.
+       pub payment_basepoint: PublicKey,
+       /// The base point which is used (with derive_public_key) to derive a per-commitment payment
+       /// public key which receives non-HTLC-encumbered funds which are only available for spending
+       /// after some delay (or can be claimed via the revocation path).
+       pub delayed_payment_basepoint: PublicKey,
+       /// The base point which is used (with derive_public_key) to derive a per-commitment public key
+       /// which is used to encumber HTLC-in-flight outputs.
+       pub htlc_basepoint: PublicKey,
 }
 
+impl_writeable!(ChannelPublicKeys, 33*5, {
+       funding_pubkey,
+       revocation_basepoint,
+       payment_basepoint,
+       delayed_payment_basepoint,
+       htlc_basepoint
+});
+
+
 impl TxCreationKeys {
-       pub(super) fn new<T: secp256k1::Signing + secp256k1::Verification>(secp_ctx: &Secp256k1<T>, per_commitment_point: &PublicKey, a_delayed_payment_base: &PublicKey, a_htlc_base: &PublicKey, b_revocation_base: &PublicKey, b_payment_base: &PublicKey, b_htlc_base: &PublicKey) -> Result<TxCreationKeys, secp256k1::Error> {
+       pub(crate) fn new<T: secp256k1::Signing + secp256k1::Verification>(secp_ctx: &Secp256k1<T>, per_commitment_point: &PublicKey, a_delayed_payment_base: &PublicKey, a_htlc_base: &PublicKey, b_revocation_base: &PublicKey, b_payment_base: &PublicKey, b_htlc_base: &PublicKey) -> Result<TxCreationKeys, secp256k1::Error> {
                Ok(TxCreationKeys {
                        per_commitment_point: per_commitment_point.clone(),
                        revocation_key: derive_public_revocation_key(&secp_ctx, &per_commitment_point, &b_revocation_base)?,
index fe63e46f35761f9d735dc8b34722b5b73a2b32ad..785123e0ee5acca0a508188b38c0d1910752966a 100644 (file)
@@ -215,10 +215,10 @@ fn do_test_monitor_temporary_update_fail(disconnect_count: usize) {
                nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
                nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
 
-               nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id());
+               nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty() });
                let reestablish_1 = get_chan_reestablish_msgs!(nodes[0], nodes[1]);
                assert_eq!(reestablish_1.len(), 1);
-               nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id());
+               nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty() });
                let reestablish_2 = get_chan_reestablish_msgs!(nodes[1], nodes[0]);
                assert_eq!(reestablish_2.len(), 1);
 
@@ -237,10 +237,10 @@ fn do_test_monitor_temporary_update_fail(disconnect_count: usize) {
                assert!(nodes[0].node.get_and_clear_pending_events().is_empty());
                assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
 
-               nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id());
+               nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty() });
                let reestablish_1 = get_chan_reestablish_msgs!(nodes[0], nodes[1]);
                assert_eq!(reestablish_1.len(), 1);
-               nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id());
+               nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty() });
                let reestablish_2 = get_chan_reestablish_msgs!(nodes[1], nodes[0]);
                assert_eq!(reestablish_2.len(), 1);
 
@@ -938,8 +938,8 @@ fn test_monitor_update_fail_reestablish() {
        commitment_signed_dance!(nodes[1], nodes[2], updates.commitment_signed, false);
 
        *nodes[1].chan_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure);
-       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id());
-       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id());
+       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty() });
+       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty() });
 
        let as_reestablish = get_event_msg!(nodes[0], MessageSendEvent::SendChannelReestablish, nodes[1].node.get_our_node_id());
        let bs_reestablish = get_event_msg!(nodes[1], MessageSendEvent::SendChannelReestablish, nodes[0].node.get_our_node_id());
@@ -954,8 +954,8 @@ fn test_monitor_update_fail_reestablish() {
        nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
        nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
 
-       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id());
-       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id());
+       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty() });
+       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty() });
 
        assert!(as_reestablish == get_event_msg!(nodes[0], MessageSendEvent::SendChannelReestablish, nodes[1].node.get_our_node_id()));
        assert!(bs_reestablish == get_event_msg!(nodes[1], MessageSendEvent::SendChannelReestablish, nodes[0].node.get_our_node_id()));
@@ -1118,8 +1118,8 @@ fn claim_while_disconnected_monitor_update_fail() {
        assert!(nodes[1].node.claim_funds(payment_preimage_1, 1_000_000));
        check_added_monitors!(nodes[1], 1);
 
-       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id());
-       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id());
+       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty() });
+       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty() });
 
        let as_reconnect = get_event_msg!(nodes[0], MessageSendEvent::SendChannelReestablish, nodes[1].node.get_our_node_id());
        let bs_reconnect = get_event_msg!(nodes[1], MessageSendEvent::SendChannelReestablish, nodes[0].node.get_our_node_id());
@@ -1246,8 +1246,8 @@ fn monitor_failed_no_reestablish_response() {
        nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
        nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
 
-       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id());
-       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id());
+       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty() });
+       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty() });
 
        let as_reconnect = get_event_msg!(nodes[0], MessageSendEvent::SendChannelReestablish, nodes[1].node.get_our_node_id());
        let bs_reconnect = get_event_msg!(nodes[1], MessageSendEvent::SendChannelReestablish, nodes[0].node.get_our_node_id());
index 3d8962b4fe6c2b35c9f82f9f3e2ea27c85dde9f3..02b1ae4ed2f58b413e8e4375716d490b6e0552e3 100644 (file)
@@ -20,7 +20,7 @@ use ln::msgs;
 use ln::msgs::{DecodeError, OptionalField, DataLossProtect};
 use ln::channelmonitor::ChannelMonitor;
 use ln::channelmanager::{PendingHTLCStatus, HTLCSource, HTLCFailReason, HTLCFailureMsg, PendingForwardHTLCInfo, RAACommitmentOrder, PaymentPreimage, PaymentHash, BREAKDOWN_TIMEOUT, MAX_LOCAL_BREAKDOWN_TIMEOUT};
-use ln::chan_utils::{LocalCommitmentTransaction, TxCreationKeys, HTLCOutputInCommitment, HTLC_SUCCESS_TX_WEIGHT, HTLC_TIMEOUT_TX_WEIGHT, make_funding_redeemscript};
+use ln::chan_utils::{LocalCommitmentTransaction, TxCreationKeys, HTLCOutputInCommitment, HTLC_SUCCESS_TX_WEIGHT, HTLC_TIMEOUT_TX_WEIGHT, make_funding_redeemscript, ChannelPublicKeys};
 use ln::chan_utils;
 use chain::chaininterface::{FeeEstimator,ConfirmationTarget};
 use chain::transaction::OutPoint;
@@ -335,11 +335,8 @@ pub(super) struct Channel<ChanSigner: ChannelKeys> {
        //implied by OUR_MAX_HTLCS: our_max_accepted_htlcs: u16,
        minimum_depth: u32,
 
-       their_funding_pubkey: Option<PublicKey>,
-       their_revocation_basepoint: Option<PublicKey>,
-       their_payment_basepoint: Option<PublicKey>,
-       their_delayed_payment_basepoint: Option<PublicKey>,
-       their_htlc_basepoint: Option<PublicKey>,
+       their_pubkeys: Option<ChannelPublicKeys>,
+
        their_cur_commitment_point: Option<PublicKey>,
 
        their_prev_commitment_point: Option<PublicKey>,
@@ -368,12 +365,6 @@ const B_OUTPUT_PLUS_SPENDING_INPUT_WEIGHT: u64 = 104; // prevout: 40, nSequence:
 /// it's 2^24.
 pub const MAX_FUNDING_SATOSHIS: u64 = (1 << 24);
 
-#[cfg(test)]
-pub const ACCEPTED_HTLC_SCRIPT_WEIGHT: usize = 138; //Here we have a diff due to HTLC CLTV expiry being < 2^15 in test
-#[cfg(not(test))]
-pub const ACCEPTED_HTLC_SCRIPT_WEIGHT: usize = 139;
-pub const OFFERED_HTLC_SCRIPT_WEIGHT: usize = 133;
-
 /// Used to return a simple Error back to ChannelManager. Will get converted to a
 /// msgs::ErrorAction::SendErrorMessage or msgs::ErrorAction::IgnoreError as appropriate with our
 /// channel_id in ChannelManager.
@@ -512,11 +503,7 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
                        their_max_accepted_htlcs: 0,
                        minimum_depth: 0, // Filled in in accept_channel
 
-                       their_funding_pubkey: None,
-                       their_revocation_basepoint: None,
-                       their_payment_basepoint: None,
-                       their_delayed_payment_basepoint: None,
-                       their_htlc_basepoint: None,
+                       their_pubkeys: None,
                        their_cur_commitment_point: None,
 
                        their_prev_commitment_point: None,
@@ -546,7 +533,14 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
        /// Assumes chain_hash has already been checked and corresponds with what we expect!
        pub fn new_from_req(fee_estimator: &FeeEstimator, keys_provider: &Arc<KeysInterface<ChanKeySigner = ChanSigner>>, their_node_id: PublicKey, their_features: InitFeatures, msg: &msgs::OpenChannel, user_id: u64, logger: Arc<Logger>, config: &UserConfig) -> Result<Channel<ChanSigner>, ChannelError> {
                let mut chan_keys = keys_provider.get_channel_keys(true);
-               chan_keys.set_remote_funding_pubkey(&msg.funding_pubkey);
+               let their_pubkeys = ChannelPublicKeys {
+                       funding_pubkey: msg.funding_pubkey,
+                       revocation_basepoint: msg.revocation_basepoint,
+                       payment_basepoint: msg.payment_basepoint,
+                       delayed_payment_basepoint: msg.delayed_payment_basepoint,
+                       htlc_basepoint: msg.htlc_basepoint
+               };
+               chan_keys.set_remote_channel_pubkeys(&their_pubkeys);
                let mut local_config = (*config).channel_options.clone();
 
                if config.own_channel_config.our_to_self_delay < BREAKDOWN_TIMEOUT {
@@ -728,11 +722,7 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
                        their_max_accepted_htlcs: msg.max_accepted_htlcs,
                        minimum_depth: config.own_channel_config.minimum_depth,
 
-                       their_funding_pubkey: Some(msg.funding_pubkey),
-                       their_revocation_basepoint: Some(msg.revocation_basepoint),
-                       their_payment_basepoint: Some(msg.payment_basepoint),
-                       their_delayed_payment_basepoint: Some(msg.delayed_payment_basepoint),
-                       their_htlc_basepoint: Some(msg.htlc_basepoint),
+                       their_pubkeys: Some(their_pubkeys),
                        their_cur_commitment_point: Some(msg.first_per_commitment_point),
 
                        their_prev_commitment_point: None,
@@ -767,11 +757,12 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
                let mut sha = Sha256::engine();
                let our_payment_basepoint = PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.payment_base_key());
 
+               let their_payment_basepoint = &self.their_pubkeys.as_ref().unwrap().payment_basepoint.serialize();
                if self.channel_outbound {
                        sha.input(&our_payment_basepoint.serialize());
-                       sha.input(&self.their_payment_basepoint.unwrap().serialize());
+                       sha.input(their_payment_basepoint);
                } else {
-                       sha.input(&self.their_payment_basepoint.unwrap().serialize());
+                       sha.input(their_payment_basepoint);
                        sha.input(&our_payment_basepoint.serialize());
                }
                let res = Sha256::from_engine(sha).into_inner();
@@ -1090,8 +1081,9 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
                let per_commitment_point = PublicKey::from_secret_key(&self.secp_ctx, &self.build_local_commitment_secret(commitment_number));
                let delayed_payment_base = PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.delayed_payment_base_key());
                let htlc_basepoint = PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.htlc_base_key());
+               let their_pubkeys = self.their_pubkeys.as_ref().unwrap();
 
-               Ok(secp_check!(TxCreationKeys::new(&self.secp_ctx, &per_commitment_point, &delayed_payment_base, &htlc_basepoint, &self.their_revocation_basepoint.unwrap(), &self.their_payment_basepoint.unwrap(), &self.their_htlc_basepoint.unwrap()), "Local tx keys generation got bogus keys"))
+               Ok(secp_check!(TxCreationKeys::new(&self.secp_ctx, &per_commitment_point, &delayed_payment_base, &htlc_basepoint, &their_pubkeys.revocation_basepoint, &their_pubkeys.payment_basepoint, &their_pubkeys.htlc_basepoint), "Local tx keys generation got bogus keys"))
        }
 
        #[inline]
@@ -1104,8 +1096,9 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
                let payment_basepoint = PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.payment_base_key());
                let revocation_basepoint = PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.revocation_base_key());
                let htlc_basepoint = PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.htlc_base_key());
+               let their_pubkeys = self.their_pubkeys.as_ref().unwrap();
 
-               Ok(secp_check!(TxCreationKeys::new(&self.secp_ctx, &self.their_cur_commitment_point.unwrap(), &self.their_delayed_payment_basepoint.unwrap(), &self.their_htlc_basepoint.unwrap(), &revocation_basepoint, &payment_basepoint, &htlc_basepoint), "Remote tx keys generation got bogus keys"))
+               Ok(secp_check!(TxCreationKeys::new(&self.secp_ctx, &self.their_cur_commitment_point.unwrap(), &their_pubkeys.delayed_payment_basepoint, &their_pubkeys.htlc_basepoint, &revocation_basepoint, &payment_basepoint, &htlc_basepoint), "Remote tx keys generation got bogus keys"))
        }
 
        /// Gets the redeemscript for the funding transaction output (ie the funding transaction output
@@ -1113,8 +1106,7 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
        /// Panics if called before accept_channel/new_from_req
        pub fn get_funding_redeemscript(&self) -> Script {
                let our_funding_key = PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.funding_key());
-               let their_funding_key = self.their_funding_pubkey.expect("get_funding_redeemscript only allowed after accept_channel");
-               make_funding_redeemscript(&our_funding_key, &their_funding_key)
+               make_funding_redeemscript(&our_funding_key, self.their_funding_pubkey())
        }
 
        /// Builds the htlc-success or htlc-timeout transaction which spends a given HTLC output
@@ -1388,11 +1380,18 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
                self.their_to_self_delay = msg.to_self_delay;
                self.their_max_accepted_htlcs = msg.max_accepted_htlcs;
                self.minimum_depth = msg.minimum_depth;
-               self.their_funding_pubkey = Some(msg.funding_pubkey);
-               self.their_revocation_basepoint = Some(msg.revocation_basepoint);
-               self.their_payment_basepoint = Some(msg.payment_basepoint);
-               self.their_delayed_payment_basepoint = Some(msg.delayed_payment_basepoint);
-               self.their_htlc_basepoint = Some(msg.htlc_basepoint);
+
+               let their_pubkeys = ChannelPublicKeys {
+                       funding_pubkey: msg.funding_pubkey,
+                       revocation_basepoint: msg.revocation_basepoint,
+                       payment_basepoint: msg.payment_basepoint,
+                       delayed_payment_basepoint: msg.delayed_payment_basepoint,
+                       htlc_basepoint: msg.htlc_basepoint
+               };
+
+               self.local_keys.set_remote_channel_pubkeys(&their_pubkeys);
+               self.their_pubkeys = Some(their_pubkeys);
+
                self.their_cur_commitment_point = Some(msg.first_per_commitment_point);
                self.their_shutdown_scriptpubkey = their_shutdown_scriptpubkey;
 
@@ -1401,7 +1400,6 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
                self.channel_monitor.set_basic_channel_info(&msg.htlc_basepoint, &msg.delayed_payment_basepoint, msg.to_self_delay, funding_redeemscript, self.channel_value_satoshis, obscure_factor);
 
                self.channel_state = ChannelState::OurInitSent as u32 | ChannelState::TheirInitSent as u32;
-               self.local_keys.set_remote_funding_pubkey(&msg.funding_pubkey);
 
                Ok(())
        }
@@ -1414,9 +1412,9 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
                let local_sighash = hash_to_message!(&bip143::SighashComponents::new(&local_initial_commitment_tx).sighash_all(&local_initial_commitment_tx.input[0], &funding_script, self.channel_value_satoshis)[..]);
 
                // They sign the "local" commitment transaction...
-               secp_check!(self.secp_ctx.verify(&local_sighash, &sig, &self.their_funding_pubkey.unwrap()), "Invalid funding_created signature from peer");
+               secp_check!(self.secp_ctx.verify(&local_sighash, &sig, self.their_funding_pubkey()), "Invalid funding_created signature from peer");
 
-               let localtx = LocalCommitmentTransaction::new_missing_local_sig(local_initial_commitment_tx, sig, &PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.funding_key()), self.their_funding_pubkey.as_ref().unwrap());
+               let localtx = LocalCommitmentTransaction::new_missing_local_sig(local_initial_commitment_tx, sig, &PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.funding_key()), self.their_funding_pubkey());
 
                let remote_keys = self.build_remote_transaction_keys()?;
                let remote_initial_commitment_tx = self.build_commitment_transaction(self.cur_remote_commitment_transaction_number, &remote_keys, false, false, self.feerate_per_kw).0;
@@ -1427,6 +1425,10 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
                Ok((remote_initial_commitment_tx, localtx, remote_signature, local_keys))
        }
 
+       fn their_funding_pubkey(&self) -> &PublicKey {
+               &self.their_pubkeys.as_ref().expect("their_funding_pubkey() only allowed after accept_channel").funding_pubkey
+       }
+
        pub fn funding_created(&mut self, msg: &msgs::FundingCreated) -> Result<(msgs::FundingSigned, ChannelMonitor), ChannelError> {
                if self.channel_outbound {
                        return Err(ChannelError::Close("Received funding_created for an outbound channel?"));
@@ -1491,11 +1493,13 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
                let local_initial_commitment_tx = self.build_commitment_transaction(self.cur_local_commitment_transaction_number, &local_keys, true, false, self.feerate_per_kw).0;
                let local_sighash = hash_to_message!(&bip143::SighashComponents::new(&local_initial_commitment_tx).sighash_all(&local_initial_commitment_tx.input[0], &funding_script, self.channel_value_satoshis)[..]);
 
+               let their_funding_pubkey = &self.their_pubkeys.as_ref().unwrap().funding_pubkey;
+
                // They sign the "local" commitment transaction, allowing us to broadcast the tx if we wish.
-               secp_check!(self.secp_ctx.verify(&local_sighash, &msg.signature, &self.their_funding_pubkey.unwrap()), "Invalid funding_signed signature from peer");
+               secp_check!(self.secp_ctx.verify(&local_sighash, &msg.signature, their_funding_pubkey), "Invalid funding_signed signature from peer");
 
                self.channel_monitor.provide_latest_local_commitment_tx_info(
-                       LocalCommitmentTransaction::new_missing_local_sig(local_initial_commitment_tx, &msg.signature, &PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.funding_key()), self.their_funding_pubkey.as_ref().unwrap()),
+                       LocalCommitmentTransaction::new_missing_local_sig(local_initial_commitment_tx, &msg.signature, &PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.funding_key()), their_funding_pubkey),
                        local_keys, self.feerate_per_kw, Vec::new());
                self.channel_state = ChannelState::FundingSent as u32 | (self.channel_state & (ChannelState::MonitorUpdateFailed as u32));
                self.cur_local_commitment_transaction_number -= 1;
@@ -1743,8 +1747,8 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
                };
                let local_commitment_txid = local_commitment_tx.0.txid();
                let local_sighash = hash_to_message!(&bip143::SighashComponents::new(&local_commitment_tx.0).sighash_all(&local_commitment_tx.0.input[0], &funding_script, self.channel_value_satoshis)[..]);
-               log_trace!(self, "Checking commitment tx signature {} by key {} against tx {} with redeemscript {}", log_bytes!(msg.signature.serialize_compact()[..]), log_bytes!(self.their_funding_pubkey.unwrap().serialize()), encode::serialize_hex(&local_commitment_tx.0), encode::serialize_hex(&funding_script));
-               secp_check!(self.secp_ctx.verify(&local_sighash, &msg.signature, &self.their_funding_pubkey.unwrap()), "Invalid commitment tx signature from peer");
+               log_trace!(self, "Checking commitment tx signature {} by key {} against tx {} with redeemscript {}", log_bytes!(msg.signature.serialize_compact()[..]), log_bytes!(self.their_funding_pubkey().serialize()), encode::serialize_hex(&local_commitment_tx.0), encode::serialize_hex(&funding_script));
+               secp_check!(self.secp_ctx.verify(&local_sighash, &msg.signature, &self.their_funding_pubkey()), "Invalid commitment tx signature from peer");
 
                //If channel fee was updated by funder confirm funder can afford the new fee rate when applied to the current local commitment transaction
                if update_fee {
@@ -1792,9 +1796,10 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
                        }
                }
 
+               let their_funding_pubkey = self.their_pubkeys.as_ref().unwrap().funding_pubkey;
 
                self.channel_monitor.provide_latest_local_commitment_tx_info(
-                       LocalCommitmentTransaction::new_missing_local_sig(local_commitment_tx.0, &msg.signature, &PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.funding_key()), self.their_funding_pubkey.as_ref().unwrap()),
+                       LocalCommitmentTransaction::new_missing_local_sig(local_commitment_tx.0, &msg.signature, &PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.funding_key()), &their_funding_pubkey),
                        local_keys, self.feerate_per_kw, htlcs_and_sigs);
 
                for htlc in self.pending_inbound_htlcs.iter_mut() {
@@ -2652,7 +2657,7 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
                tx.input[0].witness.push(Vec::new()); // First is the multisig dummy
 
                let our_funding_key = PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.funding_key()).serialize();
-               let their_funding_key = self.their_funding_pubkey.unwrap().serialize();
+               let their_funding_key = self.their_funding_pubkey().serialize();
                if our_funding_key[..] < their_funding_key[..] {
                        tx.input[0].witness.push(our_sig.serialize_der().to_vec());
                        tx.input[0].witness.push(their_sig.serialize_der().to_vec());
@@ -2687,14 +2692,16 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
                }
                let mut sighash = hash_to_message!(&bip143::SighashComponents::new(&closing_tx).sighash_all(&closing_tx.input[0], &funding_redeemscript, self.channel_value_satoshis)[..]);
 
-               match self.secp_ctx.verify(&sighash, &msg.signature, &self.their_funding_pubkey.unwrap()) {
+               let their_funding_pubkey = &self.their_pubkeys.as_ref().unwrap().funding_pubkey;
+
+               match self.secp_ctx.verify(&sighash, &msg.signature, their_funding_pubkey) {
                        Ok(_) => {},
                        Err(_e) => {
                                // The remote end may have decided to revoke their output due to inconsistent dust
                                // limits, so check for that case by re-checking the signature here.
                                closing_tx = self.build_closing_transaction(msg.fee_satoshis, true).0;
                                sighash = hash_to_message!(&bip143::SighashComponents::new(&closing_tx).sighash_all(&closing_tx.input[0], &funding_redeemscript, self.channel_value_satoshis)[..]);
-                               secp_check!(self.secp_ctx.verify(&sighash, &msg.signature, &self.their_funding_pubkey.unwrap()), "Invalid closing tx signature from peer");
+                               secp_check!(self.secp_ctx.verify(&sighash, &msg.signature, self.their_funding_pubkey()), "Invalid closing tx signature from peer");
                        },
                };
 
@@ -3227,8 +3234,8 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
                        short_channel_id: self.get_short_channel_id().unwrap(),
                        node_id_1: if were_node_one { our_node_id } else { self.get_their_node_id() },
                        node_id_2: if were_node_one { self.get_their_node_id() } else { our_node_id },
-                       bitcoin_key_1: if were_node_one { our_bitcoin_key } else { self.their_funding_pubkey.unwrap() },
-                       bitcoin_key_2: if were_node_one { self.their_funding_pubkey.unwrap() } else { our_bitcoin_key },
+                       bitcoin_key_1: if were_node_one { our_bitcoin_key } else { self.their_funding_pubkey().clone() },
+                       bitcoin_key_2: if were_node_one { self.their_funding_pubkey().clone() } else { our_bitcoin_key },
                        excess_data: Vec::new(),
                };
 
@@ -3791,11 +3798,7 @@ impl<ChanSigner: ChannelKeys + Writeable> Writeable for Channel<ChanSigner> {
                self.their_max_accepted_htlcs.write(writer)?;
                self.minimum_depth.write(writer)?;
 
-               write_option!(self.their_funding_pubkey);
-               write_option!(self.their_revocation_basepoint);
-               write_option!(self.their_payment_basepoint);
-               write_option!(self.their_delayed_payment_basepoint);
-               write_option!(self.their_htlc_basepoint);
+               write_option!(self.their_pubkeys);
                write_option!(self.their_cur_commitment_point);
 
                write_option!(self.their_prev_commitment_point);
@@ -3945,11 +3948,7 @@ impl<R : ::std::io::Read, ChanSigner: ChannelKeys + Readable<R>> ReadableArgs<R,
                let their_max_accepted_htlcs = Readable::read(reader)?;
                let minimum_depth = Readable::read(reader)?;
 
-               let their_funding_pubkey = Readable::read(reader)?;
-               let their_revocation_basepoint = Readable::read(reader)?;
-               let their_payment_basepoint = Readable::read(reader)?;
-               let their_delayed_payment_basepoint = Readable::read(reader)?;
-               let their_htlc_basepoint = Readable::read(reader)?;
+               let their_pubkeys = Readable::read(reader)?;
                let their_cur_commitment_point = Readable::read(reader)?;
 
                let their_prev_commitment_point = Readable::read(reader)?;
@@ -4022,11 +4021,7 @@ impl<R : ::std::io::Read, ChanSigner: ChannelKeys + Readable<R>> ReadableArgs<R,
                        their_max_accepted_htlcs,
                        minimum_depth,
 
-                       their_funding_pubkey,
-                       their_revocation_basepoint,
-                       their_payment_basepoint,
-                       their_delayed_payment_basepoint,
-                       their_htlc_basepoint,
+                       their_pubkeys,
                        their_cur_commitment_point,
 
                        their_prev_commitment_point,
@@ -4056,14 +4051,14 @@ mod tests {
        use ln::channel::{Channel,ChannelKeys,InboundHTLCOutput,OutboundHTLCOutput,InboundHTLCState,OutboundHTLCState,HTLCOutputInCommitment,TxCreationKeys};
        use ln::channel::MAX_FUNDING_SATOSHIS;
        use ln::chan_utils;
-       use ln::chan_utils::LocalCommitmentTransaction;
+       use ln::chan_utils::{LocalCommitmentTransaction, ChannelPublicKeys};
        use chain::chaininterface::{FeeEstimator,ConfirmationTarget};
        use chain::keysinterface::{InMemoryChannelKeys, KeysInterface};
        use chain::transaction::OutPoint;
        use util::config::UserConfig;
        use util::test_utils;
        use util::logger::Logger;
-       use secp256k1::{Secp256k1,Message,Signature};
+       use secp256k1::{Secp256k1, Message, Signature, All};
        use secp256k1::key::{SecretKey,PublicKey};
        use bitcoin_hashes::sha256::Hash as Sha256;
        use bitcoin_hashes::sha256d::Hash as Sha256dHash;
@@ -4111,6 +4106,10 @@ mod tests {
                fn get_channel_id(&self) -> [u8; 32] { [0; 32] }
        }
 
+       fn public_from_secret_hex(secp_ctx: &Secp256k1<All>, hex: &str) -> PublicKey {
+               PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&hex::decode(hex).unwrap()[..]).unwrap())
+       }
+
        #[test]
        fn outbound_commitment_test() {
                // Test vectors from BOLT 3 Appendix C:
@@ -4127,7 +4126,7 @@ mod tests {
                        // These aren't set in the test vectors:
                        revocation_base_key: SecretKey::from_slice(&hex::decode("0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap()[..]).unwrap(),
                        commitment_seed: [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff],
-                       remote_funding_pubkey: None,
+                       remote_channel_pubkeys: None,
                };
                assert_eq!(PublicKey::from_secret_key(&secp_ctx, chan_keys.funding_key()).serialize()[..],
                                hex::decode("023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb").unwrap()[..]);
@@ -4143,19 +4142,22 @@ mod tests {
                let funding_info = OutPoint::new(Sha256dHash::from_hex("8984484a580b825b9972d7adb15050b3ab624ccd731946b3eeddb92f4e7ef6be").unwrap(), 0);
                chan.channel_monitor.set_funding_info((funding_info, Script::new()));
 
-               chan.their_payment_basepoint = Some(PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&hex::decode("4444444444444444444444444444444444444444444444444444444444444444").unwrap()[..]).unwrap()));
-               assert_eq!(chan.their_payment_basepoint.unwrap().serialize()[..],
-                               hex::decode("032c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e668680991").unwrap()[..]);
+               let their_pubkeys = ChannelPublicKeys {
+                       funding_pubkey: public_from_secret_hex(&secp_ctx, "1552dfba4f6cf29a62a0af13c8d6981d36d0ef8d61ba10fb0fe90da7634d7e13"),
+                       revocation_basepoint: PublicKey::from_slice(&hex::decode("02466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f27").unwrap()[..]).unwrap(),
+                       payment_basepoint: public_from_secret_hex(&secp_ctx, "4444444444444444444444444444444444444444444444444444444444444444"),
+                       delayed_payment_basepoint: public_from_secret_hex(&secp_ctx, "1552dfba4f6cf29a62a0af13c8d6981d36d0ef8d61ba10fb0fe90da7634d7e13"),
+                       htlc_basepoint: public_from_secret_hex(&secp_ctx, "4444444444444444444444444444444444444444444444444444444444444444")
+               };
 
-               chan.their_funding_pubkey = Some(PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&hex::decode("1552dfba4f6cf29a62a0af13c8d6981d36d0ef8d61ba10fb0fe90da7634d7e13").unwrap()[..]).unwrap()));
-               assert_eq!(chan.their_funding_pubkey.unwrap().serialize()[..],
-                               hex::decode("030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c1").unwrap()[..]);
+               assert_eq!(their_pubkeys.payment_basepoint.serialize()[..],
+                          hex::decode("032c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e668680991").unwrap()[..]);
 
-               chan.their_htlc_basepoint = Some(PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&hex::decode("4444444444444444444444444444444444444444444444444444444444444444").unwrap()[..]).unwrap()));
-               assert_eq!(chan.their_htlc_basepoint.unwrap().serialize()[..],
-                               hex::decode("032c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e668680991").unwrap()[..]);
+               assert_eq!(their_pubkeys.funding_pubkey.serialize()[..],
+                          hex::decode("030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c1").unwrap()[..]);
 
-               chan.their_revocation_basepoint = Some(PublicKey::from_slice(&hex::decode("02466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f27").unwrap()[..]).unwrap());
+               assert_eq!(their_pubkeys.htlc_basepoint.serialize()[..],
+                          hex::decode("032c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e668680991").unwrap()[..]);
 
                // We can't just use build_local_transaction_keys here as the per_commitment_secret is not
                // derived from a commitment_seed, so instead we copy it here and call
@@ -4164,7 +4166,9 @@ mod tests {
                let per_commitment_secret = SecretKey::from_slice(&hex::decode("1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100").unwrap()[..]).unwrap();
                let per_commitment_point = PublicKey::from_secret_key(&secp_ctx, &per_commitment_secret);
                let htlc_basepoint = PublicKey::from_secret_key(&secp_ctx, chan.local_keys.htlc_base_key());
-               let keys = TxCreationKeys::new(&secp_ctx, &per_commitment_point, &delayed_payment_base, &htlc_basepoint, &chan.their_revocation_basepoint.unwrap(), &chan.their_payment_basepoint.unwrap(), &chan.their_htlc_basepoint.unwrap()).unwrap();
+               let keys = TxCreationKeys::new(&secp_ctx, &per_commitment_point, &delayed_payment_base, &htlc_basepoint, &their_pubkeys.revocation_basepoint, &their_pubkeys.payment_basepoint, &their_pubkeys.htlc_basepoint).unwrap();
+
+               chan.their_pubkeys = Some(their_pubkeys);
 
                let mut unsigned_tx: (Transaction, Vec<HTLCOutputInCommitment>);
 
@@ -4180,9 +4184,9 @@ mod tests {
                                let redeemscript = chan.get_funding_redeemscript();
                                let their_signature = Signature::from_der(&hex::decode($their_sig_hex).unwrap()[..]).unwrap();
                                let sighash = Message::from_slice(&bip143::SighashComponents::new(&unsigned_tx.0).sighash_all(&unsigned_tx.0.input[0], &redeemscript, chan.channel_value_satoshis)[..]).unwrap();
-                               secp_ctx.verify(&sighash, &their_signature, &chan.their_funding_pubkey.unwrap()).unwrap();
+                               secp_ctx.verify(&sighash, &their_signature, chan.their_funding_pubkey()).unwrap();
 
-                               let mut localtx = LocalCommitmentTransaction::new_missing_local_sig(unsigned_tx.0.clone(), &their_signature, &PublicKey::from_secret_key(&secp_ctx, chan.local_keys.funding_key()), chan.their_funding_pubkey.as_ref().unwrap());
+                               let mut localtx = LocalCommitmentTransaction::new_missing_local_sig(unsigned_tx.0.clone(), &their_signature, &PublicKey::from_secret_key(&secp_ctx, chan.local_keys.funding_key()), chan.their_funding_pubkey());
                                localtx.add_local_sig(chan.local_keys.funding_key(), &redeemscript, chan.channel_value_satoshis, &chan.secp_ctx);
 
                                assert_eq!(serialize(localtx.with_valid_witness())[..],
index 60fe1c4586eb89471113ffe0c8ed6ae97fb90897..18d3372024a3354838f188f109e9c5b8bcee3899 100644 (file)
@@ -275,6 +275,12 @@ pub(super) struct ChannelHolder<ChanSigner: ChannelKeys> {
        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";
 
@@ -328,6 +334,14 @@ pub struct ChannelManager<ChanSigner: ChannelKeys> {
        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.
@@ -390,6 +404,10 @@ pub struct ChannelDetails {
        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.
@@ -610,6 +628,8 @@ impl<ChanSigner: ChannelKeys> ChannelManager<ChanSigner> {
                        }),
                        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(()),
 
@@ -660,56 +680,53 @@ impl<ChanSigner: ChannelKeys> ChannelManager<ChanSigner> {
                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.
@@ -2780,6 +2797,7 @@ impl<ChanSigner: ChannelKeys> ChannelMessageHandler for ChannelManager<ChanSigne
                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;
@@ -2818,6 +2836,8 @@ impl<ChanSigner: ChannelKeys> ChannelMessageHandler for ChannelManager<ChanSigne
                                                                short_to_id.remove(&short_id);
                                                        }
                                                        return false;
+                                               } else {
+                                                       no_channels_remain = false;
                                                }
                                        }
                                        true
@@ -2843,6 +2863,10 @@ impl<ChanSigner: ChannelKeys> ChannelMessageHandler for ChannelManager<ChanSigne
                                }
                        });
                }
+               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);
                }
@@ -2853,10 +2877,25 @@ impl<ChanSigner: ChannelKeys> ChannelMessageHandler for ChannelManager<ChanSigne
                }
        }
 
-       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;
@@ -3123,6 +3162,14 @@ impl<ChanSigner: ChannelKeys + Writeable> Writeable for ChannelManager<ChanSigne
                        }
                }
 
+               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(())
        }
 }
@@ -3256,6 +3303,16 @@ impl<'a, R : ::std::io::Read, ChanSigner: ChannelKeys + Readable<R>> ReadableArg
                        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,
@@ -3275,6 +3332,8 @@ impl<'a, R : ::std::io::Read, ChanSigner: ChannelKeys + Readable<R>> ReadableArg
                        }),
                        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,
index 66e73a22d2e53b104372ac526c625aecc29b3d70..dada0bcb45d43905bb19a0c4657b18a3cc0aa74a 100644 (file)
@@ -31,9 +31,8 @@ use secp256k1;
 
 use ln::msgs::DecodeError;
 use ln::chan_utils;
-use ln::chan_utils::{HTLCOutputInCommitment, LocalCommitmentTransaction};
+use ln::chan_utils::{HTLCOutputInCommitment, LocalCommitmentTransaction, HTLCType};
 use ln::channelmanager::{HTLCSource, PaymentPreimage, PaymentHash};
-use ln::channel::{ACCEPTED_HTLC_SCRIPT_WEIGHT, OFFERED_HTLC_SCRIPT_WEIGHT};
 use chain::chaininterface::{ChainListener, ChainWatchInterface, BroadcasterInterface, FeeEstimator, ConfirmationTarget, MIN_RELAY_FEE_SAT_PER_1000_WEIGHT};
 use chain::transaction::OutPoint;
 use chain::keysinterface::SpendableOutputDescriptor;
@@ -2558,6 +2557,7 @@ impl ChannelMonitor {
        }
 
        fn block_disconnected(&mut self, height: u32, block_hash: &Sha256dHash, broadcaster: &BroadcasterInterface, fee_estimator: &FeeEstimator) {
+               log_trace!(self, "Block {} at height {} disconnected", block_hash, height);
                let mut bump_candidates = HashMap::new();
                if let Some(events) = self.onchain_events_waiting_threshold_conf.remove(&(height + ANTI_REORG_DELAY - 1)) {
                        //We may discard:
@@ -2678,10 +2678,10 @@ impl ChannelMonitor {
 
                'outer_loop: for input in &tx.input {
                        let mut payment_data = None;
-                       let revocation_sig_claim = (input.witness.len() == 3 && input.witness[2].len() == OFFERED_HTLC_SCRIPT_WEIGHT && input.witness[1].len() == 33)
-                               || (input.witness.len() == 3 && input.witness[2].len() == ACCEPTED_HTLC_SCRIPT_WEIGHT && input.witness[1].len() == 33);
-                       let accepted_preimage_claim = input.witness.len() == 5 && input.witness[4].len() == ACCEPTED_HTLC_SCRIPT_WEIGHT;
-                       let offered_preimage_claim = input.witness.len() == 3 && input.witness[2].len() == OFFERED_HTLC_SCRIPT_WEIGHT;
+                       let revocation_sig_claim = (input.witness.len() == 3 && HTLCType::scriptlen_to_htlctype(input.witness[2].len()) == Some(HTLCType::OfferedHTLC) && input.witness[1].len() == 33)
+                               || (input.witness.len() == 3 && HTLCType::scriptlen_to_htlctype(input.witness[2].len()) == Some(HTLCType::AcceptedHTLC) && input.witness[1].len() == 33);
+                       let accepted_preimage_claim = input.witness.len() == 5 && HTLCType::scriptlen_to_htlctype(input.witness[4].len()) == Some(HTLCType::AcceptedHTLC);
+                       let offered_preimage_claim = input.witness.len() == 3 && HTLCType::scriptlen_to_htlctype(input.witness[2].len()) == Some(HTLCType::OfferedHTLC);
 
                        macro_rules! log_claim {
                                ($tx_info: expr, $local_tx: expr, $htlc: expr, $source_avail: expr) => {
@@ -2872,7 +2872,8 @@ impl ChannelMonitor {
                for per_outp_material in cached_claim_datas.per_input_material.values() {
                        match per_outp_material {
                                &InputMaterial::Revoked { ref script, ref is_htlc, ref amount, .. } => {
-                                       inputs_witnesses_weight += Self::get_witnesses_weight(if !is_htlc { &[InputDescriptors::RevokedOutput] } else if script.len() == OFFERED_HTLC_SCRIPT_WEIGHT { &[InputDescriptors::RevokedOfferedHTLC] } else if script.len() == ACCEPTED_HTLC_SCRIPT_WEIGHT { &[InputDescriptors::RevokedReceivedHTLC] } else { &[] });
+                                       log_trace!(self, "Is HLTC ? {}", is_htlc);
+                                       inputs_witnesses_weight += Self::get_witnesses_weight(if !is_htlc { &[InputDescriptors::RevokedOutput] } else if HTLCType::scriptlen_to_htlctype(script.len()) == Some(HTLCType::OfferedHTLC) { &[InputDescriptors::RevokedOfferedHTLC] } else if HTLCType::scriptlen_to_htlctype(script.len()) == Some(HTLCType::AcceptedHTLC) { &[InputDescriptors::RevokedReceivedHTLC] } else { unreachable!() });
                                        amt += *amount;
                                },
                                &InputMaterial::RemoteHTLC { ref preimage, ref amount, .. } => {
@@ -2912,7 +2913,7 @@ impl ChannelMonitor {
                                                bumped_tx.input[i].witness.push(vec!(1));
                                        }
                                        bumped_tx.input[i].witness.push(script.clone().into_bytes());
-                                       log_trace!(self, "Going to broadcast bumped Penalty Transaction {} claiming revoked {} output {} from {} with new feerate {}", bumped_tx.txid(), if !is_htlc { "to_local" } else if script.len() == OFFERED_HTLC_SCRIPT_WEIGHT { "offered" } else if script.len() == ACCEPTED_HTLC_SCRIPT_WEIGHT { "received" } else { "" }, outp.vout, outp.txid, new_feerate);
+                                       log_trace!(self, "Going to broadcast bumped Penalty Transaction {} claiming revoked {} output {} from {} with new feerate {}", bumped_tx.txid(), if !is_htlc { "to_local" } else if HTLCType::scriptlen_to_htlctype(script.len()) == Some(HTLCType::OfferedHTLC) { "offered" } else if HTLCType::scriptlen_to_htlctype(script.len()) == Some(HTLCType::AcceptedHTLC) { "received" } else { "" }, outp.vout, outp.txid, new_feerate);
                                },
                                &InputMaterial::RemoteHTLC { ref script, ref key, ref preimage, ref amount, ref locktime } => {
                                        if !preimage.is_some() { bumped_tx.lock_time = *locktime };
index c334074871eb486a924da2eabdde30865dc55e22..eee534f71087215ff1f00e71be32e314ab44d623 100644 (file)
@@ -118,6 +118,13 @@ impl ChannelFeatures {
                        mark: PhantomData,
                }
        }
+
+       /// Takes the flags that we know how to interpret in an init-context features that are also
+       /// relevant in a channel-context features and creates a channel-context features from them.
+       pub(crate) fn with_known_relevant_init_flags(_init_ctx: &InitFeatures) -> Self {
+               // There are currently no channel flags defined that we understand.
+               Self { flags: Vec::new(), mark: PhantomData, }
+       }
 }
 
 impl NodeFeatures {
@@ -136,6 +143,17 @@ impl NodeFeatures {
                        mark: PhantomData,
                }
        }
+
+       /// Takes the flags that we know how to interpret in an init-context features that are also
+       /// relevant in a node-context features and creates a node-context features from them.
+       pub(crate) fn with_known_relevant_init_flags(init_ctx: &InitFeatures) -> Self {
+               let mut flags = Vec::new();
+               if init_ctx.flags.len() > 0 {
+                       // Pull out data_loss_protect and upfront_shutdown_script (bits 0, 1, 4, and 5)
+                       flags.push(init_ctx.flags.last().unwrap() & 0b00110011);
+               }
+               Self { flags, mark: PhantomData, }
+       }
 }
 
 impl<T: sealed::Context> Features<T> {
index 3936460f37eae318463543da2d45c566409bb2f1..9d15d0aec25237245eace399b4f6a35bab9f33c7 100644 (file)
@@ -876,6 +876,9 @@ pub fn create_network(node_count: usize, node_config: &[Option<UserConfig>]) ->
        nodes
 }
 
+pub const ACCEPTED_HTLC_SCRIPT_WEIGHT: usize = 138; //Here we have a diff due to HTLC CLTV expiry being < 2^15 in test
+pub const OFFERED_HTLC_SCRIPT_WEIGHT: usize = 133;
+
 #[derive(PartialEq)]
 pub enum HTLCType { NONE, TIMEOUT, SUCCESS }
 /// Tests that the given node has broadcast transactions for the given Channel
@@ -1084,9 +1087,9 @@ macro_rules! handle_chan_reestablish_msgs {
 /// pending_htlc_adds includes both the holding cell and in-flight update_add_htlcs, whereas
 /// for claims/fails they are separated out.
 pub fn reconnect_nodes(node_a: &Node, node_b: &Node, send_funding_locked: (bool, bool), pending_htlc_adds: (i64, i64), pending_htlc_claims: (usize, usize), pending_cell_htlc_claims: (usize, usize), pending_cell_htlc_fails: (usize, usize), pending_raa: (bool, bool)) {
-       node_a.node.peer_connected(&node_b.node.get_our_node_id());
+       node_a.node.peer_connected(&node_b.node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty() });
        let reestablish_1 = get_chan_reestablish_msgs!(node_a, node_b);
-       node_b.node.peer_connected(&node_a.node.get_our_node_id());
+       node_b.node.peer_connected(&node_a.node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty() });
        let reestablish_2 = get_chan_reestablish_msgs!(node_b, node_a);
 
        if send_funding_locked.0 {
index 394e40da95c25390cf516011201acb373d5e5eea..c5785ea5c2cb6a253b22083fb3e4cca3cac5f2e1 100644 (file)
@@ -8,10 +8,10 @@ use chain::keysinterface::{KeysInterface, SpendableOutputDescriptor};
 use ln::channel::{COMMITMENT_TX_BASE_WEIGHT, COMMITMENT_TX_WEIGHT_PER_HTLC};
 use ln::channelmanager::{ChannelManager,ChannelManagerReadArgs,HTLCForwardInfo,RAACommitmentOrder, PaymentPreimage, PaymentHash, BREAKDOWN_TIMEOUT};
 use ln::channelmonitor::{ChannelMonitor, CLTV_CLAIM_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS, ManyChannelMonitor, ANTI_REORG_DELAY};
-use ln::channel::{ACCEPTED_HTLC_SCRIPT_WEIGHT, OFFERED_HTLC_SCRIPT_WEIGHT, Channel, ChannelError};
+use ln::channel::{Channel, ChannelError};
 use ln::onion_utils;
 use ln::router::{Route, RouteHop};
-use ln::features::{ChannelFeatures, InitFeatures};
+use ln::features::{ChannelFeatures, InitFeatures, NodeFeatures};
 use ln::msgs;
 use ln::msgs::{ChannelMessageHandler,RoutingMessageHandler,HTLCFailChannelUpdate, ErrorAction};
 use util::enforcing_trait_impls::EnforcingChannelKeys;
@@ -852,9 +852,9 @@ fn do_test_shutdown_rebroadcast(recv_count: u8) {
        nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
        nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
 
-       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id());
+       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty() });
        let node_0_reestablish = get_event_msg!(nodes[0], MessageSendEvent::SendChannelReestablish, nodes[1].node.get_our_node_id());
-       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id());
+       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty() });
        let node_1_reestablish = get_event_msg!(nodes[1], MessageSendEvent::SendChannelReestablish, nodes[0].node.get_our_node_id());
 
        nodes[1].node.handle_channel_reestablish(&nodes[0].node.get_our_node_id(), &node_0_reestablish);
@@ -916,9 +916,9 @@ fn do_test_shutdown_rebroadcast(recv_count: u8) {
        nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
        nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
 
-       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id());
+       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty() });
        let node_0_2nd_reestablish = get_event_msg!(nodes[0], MessageSendEvent::SendChannelReestablish, nodes[1].node.get_our_node_id());
-       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id());
+       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty() });
        if recv_count == 0 {
                // If all closing_signeds weren't delivered we can just resume where we left off...
                let node_1_2nd_reestablish = get_event_msg!(nodes[1], MessageSendEvent::SendChannelReestablish, nodes[0].node.get_our_node_id());
@@ -1029,19 +1029,25 @@ fn fake_network_test() {
        let mut hops = Vec::with_capacity(3);
        hops.push(RouteHop {
                pubkey: nodes[2].node.get_our_node_id(),
+               node_features: NodeFeatures::empty(),
                short_channel_id: chan_2.0.contents.short_channel_id,
+               channel_features: ChannelFeatures::empty(),
                fee_msat: 0,
                cltv_expiry_delta: chan_3.0.contents.cltv_expiry_delta as u32
        });
        hops.push(RouteHop {
                pubkey: nodes[3].node.get_our_node_id(),
+               node_features: NodeFeatures::empty(),
                short_channel_id: chan_3.0.contents.short_channel_id,
+               channel_features: ChannelFeatures::empty(),
                fee_msat: 0,
                cltv_expiry_delta: chan_4.1.contents.cltv_expiry_delta as u32
        });
        hops.push(RouteHop {
                pubkey: nodes[1].node.get_our_node_id(),
+               node_features: NodeFeatures::empty(),
                short_channel_id: chan_4.0.contents.short_channel_id,
+               channel_features: ChannelFeatures::empty(),
                fee_msat: 1000000,
                cltv_expiry_delta: TEST_FINAL_CLTV,
        });
@@ -1052,19 +1058,25 @@ fn fake_network_test() {
        let mut hops = Vec::with_capacity(3);
        hops.push(RouteHop {
                pubkey: nodes[3].node.get_our_node_id(),
+               node_features: NodeFeatures::empty(),
                short_channel_id: chan_4.0.contents.short_channel_id,
+               channel_features: ChannelFeatures::empty(),
                fee_msat: 0,
                cltv_expiry_delta: chan_3.1.contents.cltv_expiry_delta as u32
        });
        hops.push(RouteHop {
                pubkey: nodes[2].node.get_our_node_id(),
+               node_features: NodeFeatures::empty(),
                short_channel_id: chan_3.0.contents.short_channel_id,
+               channel_features: ChannelFeatures::empty(),
                fee_msat: 0,
                cltv_expiry_delta: chan_2.1.contents.cltv_expiry_delta as u32
        });
        hops.push(RouteHop {
                pubkey: nodes[1].node.get_our_node_id(),
+               node_features: NodeFeatures::empty(),
                short_channel_id: chan_2.0.contents.short_channel_id,
+               channel_features: ChannelFeatures::empty(),
                fee_msat: 1000000,
                cltv_expiry_delta: TEST_FINAL_CLTV,
        });
@@ -3254,10 +3266,10 @@ fn test_drop_messages_peer_disconnect_dual_htlc() {
        nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
        nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
 
-       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id());
+       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty() });
        let reestablish_1 = get_chan_reestablish_msgs!(nodes[0], nodes[1]);
        assert_eq!(reestablish_1.len(), 1);
-       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id());
+       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty() });
        let reestablish_2 = get_chan_reestablish_msgs!(nodes[1], nodes[0]);
        assert_eq!(reestablish_2.len(), 1);
 
@@ -3451,9 +3463,9 @@ fn test_no_txn_manager_serialize_deserialize() {
        assert_eq!(nodes[0].node.list_channels().len(), 1);
        check_added_monitors!(nodes[0], 1);
 
-       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id());
+       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty() });
        let reestablish_1 = get_chan_reestablish_msgs!(nodes[0], nodes[1]);
-       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id());
+       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty() });
        let reestablish_2 = get_chan_reestablish_msgs!(nodes[1], nodes[0]);
 
        nodes[1].node.handle_channel_reestablish(&nodes[0].node.get_our_node_id(), &reestablish_1[0]);
@@ -3586,9 +3598,9 @@ fn test_manager_serialize_deserialize_inconsistent_monitor() {
        //... and we can even still claim the payment!
        claim_payment(&nodes[2], &[&nodes[0], &nodes[1]], our_payment_preimage, 1_000_000);
 
-       nodes[3].node.peer_connected(&nodes[0].node.get_our_node_id());
+       nodes[3].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty() });
        let reestablish = get_event_msg!(nodes[3], MessageSendEvent::SendChannelReestablish, nodes[0].node.get_our_node_id());
-       nodes[0].node.peer_connected(&nodes[3].node.get_our_node_id());
+       nodes[0].node.peer_connected(&nodes[3].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty() });
        nodes[0].node.handle_channel_reestablish(&nodes[3].node.get_our_node_id(), &reestablish);
        let msg_events = nodes[0].node.get_and_clear_pending_msg_events();
        assert_eq!(msg_events.len(), 1);
@@ -5380,10 +5392,10 @@ fn test_update_add_htlc_bolt2_receiver_check_repeated_id_ignore() {
        //Disconnect and Reconnect
        nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
        nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
-       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id());
+       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty() });
        let reestablish_1 = get_chan_reestablish_msgs!(nodes[0], nodes[1]);
        assert_eq!(reestablish_1.len(), 1);
-       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id());
+       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty() });
        let reestablish_2 = get_chan_reestablish_msgs!(nodes[1], nodes[0]);
        assert_eq!(reestablish_2.len(), 1);
        nodes[0].node.handle_channel_reestablish(&nodes[1].node.get_our_node_id(), &reestablish_2[0]);
@@ -6155,8 +6167,8 @@ fn test_data_loss_protect() {
 
        check_added_monitors!(nodes[0], 1);
 
-       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id());
-       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id());
+       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty() });
+       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty() });
 
        let reestablish_0 = get_chan_reestablish_msgs!(nodes[1], nodes[0]);
 
@@ -6297,10 +6309,10 @@ fn test_announce_disable_channels() {
                }
        }
        // Reconnect peers
-       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id());
+       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty() });
        let reestablish_1 = get_chan_reestablish_msgs!(nodes[0], nodes[1]);
        assert_eq!(reestablish_1.len(), 3);
-       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id());
+       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty() });
        let reestablish_2 = get_chan_reestablish_msgs!(nodes[1], nodes[0]);
        assert_eq!(reestablish_2.len(), 3);
 
index 875354251c5022c760d2ebe301a17478d90e3ea0..483d69e7a39ee9b3b0a0aac35a9dad46882f150f 100644 (file)
@@ -56,7 +56,10 @@ pub enum DecodeError {
 
 /// An init message to be sent or received from a peer
 pub struct Init {
+       #[cfg(not(feature = "fuzztarget"))]
        pub(crate) features: InitFeatures,
+       #[cfg(feature = "fuzztarget")]
+       pub features: InitFeatures,
 }
 
 /// An error message to be sent or received from a peer
@@ -571,7 +574,7 @@ pub trait ChannelMessageHandler : events::MessageSendEventsProvider + Send + Syn
        fn peer_disconnected(&self, their_node_id: &PublicKey, no_connection_possible: bool);
 
        /// Handle a peer reconnecting, possibly generating channel_reestablish message(s).
-       fn peer_connected(&self, their_node_id: &PublicKey);
+       fn peer_connected(&self, their_node_id: &PublicKey, msg: &Init);
        /// Handle an incoming channel_reestablish message from the given peer.
        fn handle_channel_reestablish(&self, their_node_id: &PublicKey, msg: &ChannelReestablish);
 
index c8d3bae5fde58c45ef5cd0b708aa1db52be5a48a..98f4b64496eadbdbab31efb2e6cfa5f9ad734f52 100644 (file)
@@ -425,6 +425,7 @@ pub(super) fn process_onion_failure<T: secp256k1::Signing>(secp_ctx: &Secp256k1<
 #[cfg(test)]
 mod tests {
        use ln::channelmanager::PaymentHash;
+       use ln::features::{ChannelFeatures, NodeFeatures};
        use ln::router::{Route, RouteHop};
        use ln::msgs;
        use util::ser::Writeable;
@@ -444,22 +445,27 @@ mod tests {
                        hops: vec!(
                                        RouteHop {
                                                pubkey: PublicKey::from_slice(&hex::decode("02eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619").unwrap()[..]).unwrap(),
+                                               channel_features: ChannelFeatures::empty(), node_features: NodeFeatures::empty(),
                                                short_channel_id: 0, fee_msat: 0, cltv_expiry_delta: 0 // Test vectors are garbage and not generateble from a RouteHop, we fill in payloads manually
                                        },
                                        RouteHop {
                                                pubkey: PublicKey::from_slice(&hex::decode("0324653eac434488002cc06bbfb7f10fe18991e35f9fe4302dbea6d2353dc0ab1c").unwrap()[..]).unwrap(),
+                                               channel_features: ChannelFeatures::empty(), node_features: NodeFeatures::empty(),
                                                short_channel_id: 0, fee_msat: 0, cltv_expiry_delta: 0 // Test vectors are garbage and not generateble from a RouteHop, we fill in payloads manually
                                        },
                                        RouteHop {
                                                pubkey: PublicKey::from_slice(&hex::decode("027f31ebc5462c1fdce1b737ecff52d37d75dea43ce11c74d25aa297165faa2007").unwrap()[..]).unwrap(),
+                                               channel_features: ChannelFeatures::empty(), node_features: NodeFeatures::empty(),
                                                short_channel_id: 0, fee_msat: 0, cltv_expiry_delta: 0 // Test vectors are garbage and not generateble from a RouteHop, we fill in payloads manually
                                        },
                                        RouteHop {
                                                pubkey: PublicKey::from_slice(&hex::decode("032c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e668680991").unwrap()[..]).unwrap(),
+                                               channel_features: ChannelFeatures::empty(), node_features: NodeFeatures::empty(),
                                                short_channel_id: 0, fee_msat: 0, cltv_expiry_delta: 0 // Test vectors are garbage and not generateble from a RouteHop, we fill in payloads manually
                                        },
                                        RouteHop {
                                                pubkey: PublicKey::from_slice(&hex::decode("02edabbd16b41c8371b92ef2f04c1185b4f03b6dcd52ba9b78d9d7c89c8f221145").unwrap()[..]).unwrap(),
+                                               channel_features: ChannelFeatures::empty(), node_features: NodeFeatures::empty(),
                                                short_channel_id: 0, fee_msat: 0, cltv_expiry_delta: 0 // Test vectors are garbage and not generateble from a RouteHop, we fill in payloads manually
                                        },
                        ),
index 41e210dfe502840d8e108970a79e04c0f4bb6ece..481737f362adbef751ca121bf1a470ac00258f20 100644 (file)
@@ -622,7 +622,6 @@ impl<Descriptor: SocketDescriptor> PeerManager<Descriptor> {
                                                                                                        peer.sync_status = InitSyncTracker::ChannelsSyncing(0);
                                                                                                        peers.peers_needing_send.insert(peer_descriptor.clone());
                                                                                                }
-                                                                                               peer.their_features = Some(msg.features);
 
                                                                                                if !peer.outbound {
                                                                                                        let mut features = InitFeatures::supported();
@@ -636,7 +635,8 @@ impl<Descriptor: SocketDescriptor> PeerManager<Descriptor> {
                                                                                                        }, 16);
                                                                                                }
 
-                                                                                               self.message_handler.chan_handler.peer_connected(&peer.their_node_id.unwrap());
+                                                                                               self.message_handler.chan_handler.peer_connected(&peer.their_node_id.unwrap(), &msg);
+                                                                                               peer.their_features = Some(msg.features);
                                                                                        },
                                                                                        17 => {
                                                                                                let msg = try_potential_decodeerror!(msgs::ErrorMessage::read(&mut reader));
index 15390f98ef74db04b2dd9bf2d64a9a76321f56d5..0025656087bce2228a7376f2af906a5e0c131e7d 100644 (file)
@@ -31,8 +31,14 @@ use std;
 pub struct RouteHop {
        /// The node_id of the node at this hop.
        pub pubkey: PublicKey,
+       /// The node_announcement features of the node at this hop. For the last hop, these may be
+       /// amended to match the features present in the invoice this node generated.
+       pub node_features: NodeFeatures,
        /// The channel that should be used from the previous hop to reach this node.
        pub short_channel_id: u64,
+       /// The channel_announcement features of the channel that should be used from the previous hop
+       /// to reach this node.
+       pub channel_features: ChannelFeatures,
        /// The fee taken on this hop. For the last hop, this should be the full value of the payment.
        pub fee_msat: u64,
        /// The CLTV delta added for this hop. For the last hop, this should be the full CLTV value
@@ -54,7 +60,9 @@ impl Writeable for Route {
                (self.hops.len() as u8).write(writer)?;
                for hop in self.hops.iter() {
                        hop.pubkey.write(writer)?;
+                       hop.node_features.write(writer)?;
                        hop.short_channel_id.write(writer)?;
+                       hop.channel_features.write(writer)?;
                        hop.fee_msat.write(writer)?;
                        hop.cltv_expiry_delta.write(writer)?;
                }
@@ -69,7 +77,9 @@ impl<R: ::std::io::Read> Readable<R> for Route {
                for _ in 0..hops_count {
                        hops.push(RouteHop {
                                pubkey: Readable::read(reader)?,
+                               node_features: Readable::read(reader)?,
                                short_channel_id: Readable::read(reader)?,
+                               channel_features: Readable::read(reader)?,
                                fee_msat: Readable::read(reader)?,
                                cltv_expiry_delta: Readable::read(reader)?,
                        });
@@ -840,13 +850,15 @@ impl Router {
                                        return Ok(Route {
                                                hops: vec![RouteHop {
                                                        pubkey: chan.remote_network_id,
+                                                       node_features: NodeFeatures::with_known_relevant_init_flags(&chan.counterparty_features),
                                                        short_channel_id,
+                                                       channel_features: ChannelFeatures::with_known_relevant_init_flags(&chan.counterparty_features),
                                                        fee_msat: final_value_msat,
                                                        cltv_expiry_delta: final_cltv,
                                                }],
                                        });
                                }
-                               first_hop_targets.insert(chan.remote_network_id, short_channel_id);
+                               first_hop_targets.insert(chan.remote_network_id, (short_channel_id, chan.counterparty_features.clone()));
                        }
                        if first_hop_targets.is_empty() {
                                return Err(LightningError{err: "Cannot route when there are no outbound routes away from us", action: ErrorAction::IgnoreError});
@@ -857,7 +869,7 @@ impl Router {
                        // Adds entry which goes from the node pointed to by $directional_info to
                        // $dest_node_id over the channel with id $chan_id with fees described in
                        // $directional_info.
-                       ( $chan_id: expr, $dest_node_id: expr, $directional_info: expr, $starting_fee_msat: expr ) => {
+                       ( $chan_id: expr, $dest_node_id: expr, $directional_info: expr, $chan_features: expr, $starting_fee_msat: expr ) => {
                                //TODO: Explore simply adding fee to hit htlc_minimum_msat
                                if $starting_fee_msat as u64 + final_value_msat >= $directional_info.htlc_minimum_msat {
                                        let proportional_fee_millions = ($starting_fee_msat + final_value_msat).checked_mul($directional_info.fee_proportional_millionths as u64);
@@ -873,7 +885,9 @@ impl Router {
                                                                node.lowest_inbound_channel_fee_proportional_millionths,
                                                                RouteHop {
                                                                        pubkey: $dest_node_id.clone(),
+                                                                       node_features: NodeFeatures::empty(),
                                                                        short_channel_id: 0,
+                                                                       channel_features: $chan_features.clone(),
                                                                        fee_msat: 0,
                                                                        cltv_expiry_delta: 0,
                                                        })
@@ -899,7 +913,9 @@ impl Router {
                                                        old_entry.0 = total_fee;
                                                        old_entry.3 = RouteHop {
                                                                pubkey: $dest_node_id.clone(),
+                                                               node_features: NodeFeatures::empty(),
                                                                short_channel_id: $chan_id.clone(),
+                                                               channel_features: $chan_features.clone(),
                                                                fee_msat: new_fee, // This field is ignored on the last-hop anyway
                                                                cltv_expiry_delta: $directional_info.cltv_expiry_delta as u32,
                                                        }
@@ -912,8 +928,8 @@ impl Router {
                macro_rules! add_entries_to_cheapest_to_target_node {
                        ( $node: expr, $node_id: expr, $fee_to_target_msat: expr ) => {
                                if first_hops.is_some() {
-                                       if let Some(first_hop) = first_hop_targets.get(&$node_id) {
-                                               add_entry!(first_hop, $node_id, dummy_directional_info, $fee_to_target_msat);
+                                       if let Some(&(ref first_hop, ref features)) = first_hop_targets.get(&$node_id) {
+                                               add_entry!(first_hop, $node_id, dummy_directional_info, ChannelFeatures::with_known_relevant_init_flags(&features), $fee_to_target_msat);
                                        }
                                }
 
@@ -925,13 +941,13 @@ impl Router {
                                                                // ie $node is one, ie next hop in A* is two, via the two_to_one channel
                                                                if first_hops.is_none() || chan.two_to_one.src_node_id != network.our_node_id {
                                                                        if chan.two_to_one.enabled {
-                                                                               add_entry!(chan_id, chan.one_to_two.src_node_id, chan.two_to_one, $fee_to_target_msat);
+                                                                               add_entry!(chan_id, chan.one_to_two.src_node_id, chan.two_to_one, chan.features, $fee_to_target_msat);
                                                                        }
                                                                }
                                                        } else {
                                                                if first_hops.is_none() || chan.one_to_two.src_node_id != network.our_node_id {
                                                                        if chan.one_to_two.enabled {
-                                                                               add_entry!(chan_id, chan.two_to_one.src_node_id, chan.one_to_two, $fee_to_target_msat);
+                                                                               add_entry!(chan_id, chan.two_to_one.src_node_id, chan.one_to_two, chan.features, $fee_to_target_msat);
                                                                        }
                                                                }
                                                        }
@@ -952,11 +968,17 @@ impl Router {
                        if first_hops.is_none() || hop.src_node_id != network.our_node_id { // first_hop overrules last_hops
                                if network.nodes.get(&hop.src_node_id).is_some() {
                                        if first_hops.is_some() {
-                                               if let Some(first_hop) = first_hop_targets.get(&hop.src_node_id) {
-                                                       add_entry!(first_hop, hop.src_node_id, dummy_directional_info, 0);
+                                               if let Some(&(ref first_hop, ref features)) = first_hop_targets.get(&hop.src_node_id) {
+                                                       // Currently there are no channel-context features defined, so we are a
+                                                       // bit lazy here. In the future, we should pull them out via our
+                                                       // ChannelManager, but there's no reason to waste the space until we
+                                                       // need them.
+                                                       add_entry!(first_hop, hop.src_node_id, dummy_directional_info, ChannelFeatures::with_known_relevant_init_flags(&features), 0);
                                                }
                                        }
-                                       add_entry!(hop.short_channel_id, target, hop, 0);
+                                       // BOLT 11 doesn't allow inclusion of features for the last hop hints, which
+                                       // really sucks, cause we're gonna need that eventually.
+                                       add_entry!(hop.short_channel_id, target, hop, ChannelFeatures::empty(), 0);
                                }
                        }
                }
@@ -964,7 +986,22 @@ impl Router {
                while let Some(RouteGraphNode { pubkey, lowest_fee_to_node, .. }) = targets.pop() {
                        if pubkey == network.our_node_id {
                                let mut res = vec!(dist.remove(&network.our_node_id).unwrap().3);
-                               while res.last().unwrap().pubkey != *target {
+                               loop {
+                                       if let Some(&(_, ref features)) = first_hop_targets.get(&res.last().unwrap().pubkey) {
+                                               res.last_mut().unwrap().node_features = NodeFeatures::with_known_relevant_init_flags(&features);
+                                       } else if let Some(node) = network.nodes.get(&res.last().unwrap().pubkey) {
+                                               res.last_mut().unwrap().node_features = node.features.clone();
+                                       } else {
+                                               // We should be able to fill in features for everything except the last
+                                               // hop, if the last hop was provided via a BOLT 11 invoice (though we
+                                               // should be able to extend it further as BOLT 11 does have feature
+                                               // flags for the last hop node itself).
+                                               assert!(res.last().unwrap().pubkey == *target);
+                                       }
+                                       if res.last().unwrap().pubkey == *target {
+                                               break;
+                                       }
+
                                        let new_entry = match dist.remove(&res.last().unwrap().pubkey) {
                                                Some(hop) => hop.3,
                                                None => return Err(LightningError{err: "Failed to find a non-fee-overflowing path to the given destination", action: ErrorAction::IgnoreError}),
@@ -997,7 +1034,7 @@ mod tests {
        use chain::chaininterface;
        use ln::channelmanager;
        use ln::router::{Router,NodeInfo,NetworkMap,ChannelInfo,DirectionalChannelInfo,RouteHint};
-       use ln::features::{ChannelFeatures, NodeFeatures};
+       use ln::features::{ChannelFeatures, InitFeatures, NodeFeatures};
        use ln::msgs::{LightningError, ErrorAction};
        use util::test_utils;
        use util::test_utils::TestVecWriter;
@@ -1091,6 +1128,23 @@ mod tests {
 
                let zero_hash = Sha256dHash::hash(&[0; 32]);
 
+               macro_rules! id_to_feature_flags {
+                       // Set the feature flags to the id'th odd (ie non-required) feature bit so that we can
+                       // test for it later.
+                       ($id: expr) => { {
+                               let idx = ($id - 1) * 2 + 1;
+                               if idx > 8*3 {
+                                       vec![1 << (idx - 8*3), 0, 0, 0]
+                               } else if idx > 8*2 {
+                                       vec![1 << (idx - 8*2), 0, 0]
+                               } else if idx > 8*1 {
+                                       vec![1 << (idx - 8*1), 0]
+                               } else {
+                                       vec![1 << idx]
+                               }
+                       } }
+               }
+
                {
                        let mut network = router.network_map.write().unwrap();
 
@@ -1098,7 +1152,7 @@ mod tests {
                                channels: vec!(NetworkMap::get_key(1, zero_hash.clone()), NetworkMap::get_key(3, zero_hash.clone())),
                                lowest_inbound_channel_fee_base_msat: 100,
                                lowest_inbound_channel_fee_proportional_millionths: 0,
-                               features: NodeFeatures::empty(),
+                               features: NodeFeatures::from_le_bytes(id_to_feature_flags!(1)),
                                last_update: 1,
                                rgb: [0; 3],
                                alias: [0; 32],
@@ -1106,7 +1160,7 @@ mod tests {
                                announcement_message: None,
                        });
                        network.channels.insert(NetworkMap::get_key(1, zero_hash.clone()), ChannelInfo {
-                               features: ChannelFeatures::empty(),
+                               features: ChannelFeatures::from_le_bytes(id_to_feature_flags!(1)),
                                one_to_two: DirectionalChannelInfo {
                                        src_node_id: our_id.clone(),
                                        last_update: 0,
@@ -1132,7 +1186,7 @@ mod tests {
                                channels: vec!(NetworkMap::get_key(2, zero_hash.clone()), NetworkMap::get_key(4, zero_hash.clone())),
                                lowest_inbound_channel_fee_base_msat: 0,
                                lowest_inbound_channel_fee_proportional_millionths: 0,
-                               features: NodeFeatures::empty(),
+                               features: NodeFeatures::from_le_bytes(id_to_feature_flags!(2)),
                                last_update: 1,
                                rgb: [0; 3],
                                alias: [0; 32],
@@ -1140,7 +1194,7 @@ mod tests {
                                announcement_message: None,
                        });
                        network.channels.insert(NetworkMap::get_key(2, zero_hash.clone()), ChannelInfo {
-                               features: ChannelFeatures::empty(),
+                               features: ChannelFeatures::from_le_bytes(id_to_feature_flags!(2)),
                                one_to_two: DirectionalChannelInfo {
                                        src_node_id: our_id.clone(),
                                        last_update: 0,
@@ -1166,7 +1220,7 @@ mod tests {
                                channels: vec!(NetworkMap::get_key(12, zero_hash.clone()), NetworkMap::get_key(13, zero_hash.clone())),
                                lowest_inbound_channel_fee_base_msat: 0,
                                lowest_inbound_channel_fee_proportional_millionths: 0,
-                               features: NodeFeatures::empty(),
+                               features: NodeFeatures::from_le_bytes(id_to_feature_flags!(8)),
                                last_update: 1,
                                rgb: [0; 3],
                                alias: [0; 32],
@@ -1174,7 +1228,7 @@ mod tests {
                                announcement_message: None,
                        });
                        network.channels.insert(NetworkMap::get_key(12, zero_hash.clone()), ChannelInfo {
-                               features: ChannelFeatures::empty(),
+                               features: ChannelFeatures::from_le_bytes(id_to_feature_flags!(12)),
                                one_to_two: DirectionalChannelInfo {
                                        src_node_id: our_id.clone(),
                                        last_update: 0,
@@ -1206,7 +1260,7 @@ mod tests {
                                        NetworkMap::get_key(7, zero_hash.clone())),
                                lowest_inbound_channel_fee_base_msat: 0,
                                lowest_inbound_channel_fee_proportional_millionths: 0,
-                               features: NodeFeatures::empty(),
+                               features: NodeFeatures::from_le_bytes(id_to_feature_flags!(3)),
                                last_update: 1,
                                rgb: [0; 3],
                                alias: [0; 32],
@@ -1214,7 +1268,7 @@ mod tests {
                                announcement_message: None,
                        });
                        network.channels.insert(NetworkMap::get_key(3, zero_hash.clone()), ChannelInfo {
-                               features: ChannelFeatures::empty(),
+                               features: ChannelFeatures::from_le_bytes(id_to_feature_flags!(3)),
                                one_to_two: DirectionalChannelInfo {
                                        src_node_id: node1.clone(),
                                        last_update: 0,
@@ -1237,7 +1291,7 @@ mod tests {
                                announcement_message: None,
                        });
                        network.channels.insert(NetworkMap::get_key(4, zero_hash.clone()), ChannelInfo {
-                               features: ChannelFeatures::empty(),
+                               features: ChannelFeatures::from_le_bytes(id_to_feature_flags!(4)),
                                one_to_two: DirectionalChannelInfo {
                                        src_node_id: node2.clone(),
                                        last_update: 0,
@@ -1260,7 +1314,7 @@ mod tests {
                                announcement_message: None,
                        });
                        network.channels.insert(NetworkMap::get_key(13, zero_hash.clone()), ChannelInfo {
-                               features: ChannelFeatures::empty(),
+                               features: ChannelFeatures::from_le_bytes(id_to_feature_flags!(13)),
                                one_to_two: DirectionalChannelInfo {
                                        src_node_id: node8.clone(),
                                        last_update: 0,
@@ -1286,7 +1340,7 @@ mod tests {
                                channels: vec!(NetworkMap::get_key(5, zero_hash.clone()), NetworkMap::get_key(11, zero_hash.clone())),
                                lowest_inbound_channel_fee_base_msat: 0,
                                lowest_inbound_channel_fee_proportional_millionths: 0,
-                               features: NodeFeatures::empty(),
+                               features: NodeFeatures::from_le_bytes(id_to_feature_flags!(4)),
                                last_update: 1,
                                rgb: [0; 3],
                                alias: [0; 32],
@@ -1294,7 +1348,7 @@ mod tests {
                                announcement_message: None,
                        });
                        network.channels.insert(NetworkMap::get_key(5, zero_hash.clone()), ChannelInfo {
-                               features: ChannelFeatures::empty(),
+                               features: ChannelFeatures::from_le_bytes(id_to_feature_flags!(5)),
                                one_to_two: DirectionalChannelInfo {
                                        src_node_id: node3.clone(),
                                        last_update: 0,
@@ -1320,7 +1374,7 @@ mod tests {
                                channels: vec!(NetworkMap::get_key(6, zero_hash.clone()), NetworkMap::get_key(11, zero_hash.clone())),
                                lowest_inbound_channel_fee_base_msat: 0,
                                lowest_inbound_channel_fee_proportional_millionths: 0,
-                               features: NodeFeatures::empty(),
+                               features: NodeFeatures::from_le_bytes(id_to_feature_flags!(5)),
                                last_update: 1,
                                rgb: [0; 3],
                                alias: [0; 32],
@@ -1328,7 +1382,7 @@ mod tests {
                                announcement_message: None,
                        });
                        network.channels.insert(NetworkMap::get_key(6, zero_hash.clone()), ChannelInfo {
-                               features: ChannelFeatures::empty(),
+                               features: ChannelFeatures::from_le_bytes(id_to_feature_flags!(6)),
                                one_to_two: DirectionalChannelInfo {
                                        src_node_id: node3.clone(),
                                        last_update: 0,
@@ -1351,7 +1405,7 @@ mod tests {
                                announcement_message: None,
                        });
                        network.channels.insert(NetworkMap::get_key(11, zero_hash.clone()), ChannelInfo {
-                               features: ChannelFeatures::empty(),
+                               features: ChannelFeatures::from_le_bytes(id_to_feature_flags!(11)),
                                one_to_two: DirectionalChannelInfo {
                                        src_node_id: node5.clone(),
                                        last_update: 0,
@@ -1377,7 +1431,7 @@ mod tests {
                                channels: vec!(NetworkMap::get_key(7, zero_hash.clone())),
                                lowest_inbound_channel_fee_base_msat: 0,
                                lowest_inbound_channel_fee_proportional_millionths: 0,
-                               features: NodeFeatures::empty(),
+                               features: NodeFeatures::from_le_bytes(id_to_feature_flags!(6)),
                                last_update: 1,
                                rgb: [0; 3],
                                alias: [0; 32],
@@ -1385,7 +1439,7 @@ mod tests {
                                announcement_message: None,
                        });
                        network.channels.insert(NetworkMap::get_key(7, zero_hash.clone()), ChannelInfo {
-                               features: ChannelFeatures::empty(),
+                               features: ChannelFeatures::from_le_bytes(id_to_feature_flags!(7)),
                                one_to_two: DirectionalChannelInfo {
                                        src_node_id: node3.clone(),
                                        last_update: 0,
@@ -1417,11 +1471,15 @@ mod tests {
                        assert_eq!(route.hops[0].short_channel_id, 2);
                        assert_eq!(route.hops[0].fee_msat, 100);
                        assert_eq!(route.hops[0].cltv_expiry_delta, (4 << 8) | 1);
+                       assert_eq!(route.hops[0].node_features.le_flags(), &id_to_feature_flags!(2));
+                       assert_eq!(route.hops[0].channel_features.le_flags(), &id_to_feature_flags!(2));
 
                        assert_eq!(route.hops[1].pubkey, node3);
                        assert_eq!(route.hops[1].short_channel_id, 4);
                        assert_eq!(route.hops[1].fee_msat, 100);
                        assert_eq!(route.hops[1].cltv_expiry_delta, 42);
+                       assert_eq!(route.hops[1].node_features.le_flags(), &id_to_feature_flags!(3));
+                       assert_eq!(route.hops[1].channel_features.le_flags(), &id_to_feature_flags!(4));
                }
 
                { // Disable channels 4 and 12 by requiring unknown feature bits
@@ -1441,6 +1499,7 @@ mod tests {
                                channel_id: [0; 32],
                                short_channel_id: Some(42),
                                remote_network_id: node8.clone(),
+                               counterparty_features: InitFeatures::from_le_bytes(vec![0b11]),
                                channel_value_satoshis: 0,
                                user_id: 0,
                                outbound_capacity_msat: 0,
@@ -1454,11 +1513,15 @@ mod tests {
                        assert_eq!(route.hops[0].short_channel_id, 42);
                        assert_eq!(route.hops[0].fee_msat, 200);
                        assert_eq!(route.hops[0].cltv_expiry_delta, (13 << 8) | 1);
+                       assert_eq!(route.hops[0].node_features.le_flags(), &vec![0b11]); // it should also override our view of their features
+                       assert_eq!(route.hops[0].channel_features.le_flags(), &Vec::new()); // No feature flags will meet the relevant-to-channel conversion
 
                        assert_eq!(route.hops[1].pubkey, node3);
                        assert_eq!(route.hops[1].short_channel_id, 13);
                        assert_eq!(route.hops[1].fee_msat, 100);
                        assert_eq!(route.hops[1].cltv_expiry_delta, 42);
+                       assert_eq!(route.hops[1].node_features.le_flags(), &id_to_feature_flags!(3));
+                       assert_eq!(route.hops[1].channel_features.le_flags(), &id_to_feature_flags!(13));
                }
 
                { // Re-enable channels 4 and 12 by wiping the unknown feature bits
@@ -1485,6 +1548,7 @@ mod tests {
                                channel_id: [0; 32],
                                short_channel_id: Some(42),
                                remote_network_id: node8.clone(),
+                               counterparty_features: InitFeatures::from_le_bytes(vec![0b11]),
                                channel_value_satoshis: 0,
                                user_id: 0,
                                outbound_capacity_msat: 0,
@@ -1498,11 +1562,15 @@ mod tests {
                        assert_eq!(route.hops[0].short_channel_id, 42);
                        assert_eq!(route.hops[0].fee_msat, 200);
                        assert_eq!(route.hops[0].cltv_expiry_delta, (13 << 8) | 1);
+                       assert_eq!(route.hops[0].node_features.le_flags(), &vec![0b11]); // it should also override our view of their features
+                       assert_eq!(route.hops[0].channel_features.le_flags(), &Vec::new()); // No feature flags will meet the relevant-to-channel conversion
 
                        assert_eq!(route.hops[1].pubkey, node3);
                        assert_eq!(route.hops[1].short_channel_id, 13);
                        assert_eq!(route.hops[1].fee_msat, 100);
                        assert_eq!(route.hops[1].cltv_expiry_delta, 42);
+                       assert_eq!(route.hops[1].node_features.le_flags(), &id_to_feature_flags!(3));
+                       assert_eq!(route.hops[1].channel_features.le_flags(), &id_to_feature_flags!(13));
                }
 
                { // Re-enable nodes 1, 2, and 8
@@ -1524,16 +1592,22 @@ mod tests {
                        assert_eq!(route.hops[0].short_channel_id, 2);
                        assert_eq!(route.hops[0].fee_msat, 200);
                        assert_eq!(route.hops[0].cltv_expiry_delta, (4 << 8) | 1);
+                       assert_eq!(route.hops[0].node_features.le_flags(), &id_to_feature_flags!(2));
+                       assert_eq!(route.hops[0].channel_features.le_flags(), &id_to_feature_flags!(2));
 
                        assert_eq!(route.hops[1].pubkey, node3);
                        assert_eq!(route.hops[1].short_channel_id, 4);
                        assert_eq!(route.hops[1].fee_msat, 100);
                        assert_eq!(route.hops[1].cltv_expiry_delta, (3 << 8) | 2);
+                       assert_eq!(route.hops[1].node_features.le_flags(), &id_to_feature_flags!(3));
+                       assert_eq!(route.hops[1].channel_features.le_flags(), &id_to_feature_flags!(4));
 
                        assert_eq!(route.hops[2].pubkey, node1);
                        assert_eq!(route.hops[2].short_channel_id, 3);
                        assert_eq!(route.hops[2].fee_msat, 100);
                        assert_eq!(route.hops[2].cltv_expiry_delta, 42);
+                       assert_eq!(route.hops[2].node_features.le_flags(), &id_to_feature_flags!(1));
+                       assert_eq!(route.hops[2].channel_features.le_flags(), &id_to_feature_flags!(3));
                }
 
                { // If we specify a channel to node8, that overrides our local channel view and that gets used
@@ -1541,6 +1615,7 @@ mod tests {
                                channel_id: [0; 32],
                                short_channel_id: Some(42),
                                remote_network_id: node8.clone(),
+                               counterparty_features: InitFeatures::from_le_bytes(vec![0b11]),
                                channel_value_satoshis: 0,
                                user_id: 0,
                                outbound_capacity_msat: 0,
@@ -1554,11 +1629,15 @@ mod tests {
                        assert_eq!(route.hops[0].short_channel_id, 42);
                        assert_eq!(route.hops[0].fee_msat, 200);
                        assert_eq!(route.hops[0].cltv_expiry_delta, (13 << 8) | 1);
+                       assert_eq!(route.hops[0].node_features.le_flags(), &vec![0b11]);
+                       assert_eq!(route.hops[0].channel_features.le_flags(), &Vec::new()); // No feature flags will meet the relevant-to-channel conversion
 
                        assert_eq!(route.hops[1].pubkey, node3);
                        assert_eq!(route.hops[1].short_channel_id, 13);
                        assert_eq!(route.hops[1].fee_msat, 100);
                        assert_eq!(route.hops[1].cltv_expiry_delta, 42);
+                       assert_eq!(route.hops[1].node_features.le_flags(), &id_to_feature_flags!(3));
+                       assert_eq!(route.hops[1].channel_features.le_flags(), &id_to_feature_flags!(13));
                }
 
                let mut last_hops = vec!(RouteHint {
@@ -1592,26 +1671,38 @@ mod tests {
                        assert_eq!(route.hops[0].short_channel_id, 2);
                        assert_eq!(route.hops[0].fee_msat, 100);
                        assert_eq!(route.hops[0].cltv_expiry_delta, (4 << 8) | 1);
+                       assert_eq!(route.hops[0].node_features.le_flags(), &id_to_feature_flags!(2));
+                       assert_eq!(route.hops[0].channel_features.le_flags(), &id_to_feature_flags!(2));
 
                        assert_eq!(route.hops[1].pubkey, node3);
                        assert_eq!(route.hops[1].short_channel_id, 4);
                        assert_eq!(route.hops[1].fee_msat, 0);
                        assert_eq!(route.hops[1].cltv_expiry_delta, (6 << 8) | 1);
+                       assert_eq!(route.hops[1].node_features.le_flags(), &id_to_feature_flags!(3));
+                       assert_eq!(route.hops[1].channel_features.le_flags(), &id_to_feature_flags!(4));
 
                        assert_eq!(route.hops[2].pubkey, node5);
                        assert_eq!(route.hops[2].short_channel_id, 6);
                        assert_eq!(route.hops[2].fee_msat, 0);
                        assert_eq!(route.hops[2].cltv_expiry_delta, (11 << 8) | 1);
+                       assert_eq!(route.hops[2].node_features.le_flags(), &id_to_feature_flags!(5));
+                       assert_eq!(route.hops[2].channel_features.le_flags(), &id_to_feature_flags!(6));
 
                        assert_eq!(route.hops[3].pubkey, node4);
                        assert_eq!(route.hops[3].short_channel_id, 11);
                        assert_eq!(route.hops[3].fee_msat, 0);
                        assert_eq!(route.hops[3].cltv_expiry_delta, (8 << 8) | 1);
+                       // If we have a peer in the node map, we'll use their features here since we don't have
+                       // a way of figuring out their features from the invoice:
+                       assert_eq!(route.hops[3].node_features.le_flags(), &id_to_feature_flags!(4));
+                       assert_eq!(route.hops[3].channel_features.le_flags(), &id_to_feature_flags!(11));
 
                        assert_eq!(route.hops[4].pubkey, node7);
                        assert_eq!(route.hops[4].short_channel_id, 8);
                        assert_eq!(route.hops[4].fee_msat, 100);
                        assert_eq!(route.hops[4].cltv_expiry_delta, 42);
+                       assert_eq!(route.hops[4].node_features.le_flags(), &Vec::new()); // We dont pass flags in from invoices yet
+                       assert_eq!(route.hops[4].channel_features.le_flags(), &Vec::new()); // We can't learn any flags from invoices, sadly
                }
 
                { // Simple test with outbound channel to 4 to test that last_hops and first_hops connect
@@ -1619,6 +1710,7 @@ mod tests {
                                channel_id: [0; 32],
                                short_channel_id: Some(42),
                                remote_network_id: node4.clone(),
+                               counterparty_features: InitFeatures::from_le_bytes(vec![0b11]),
                                channel_value_satoshis: 0,
                                user_id: 0,
                                outbound_capacity_msat: 0,
@@ -1632,11 +1724,15 @@ mod tests {
                        assert_eq!(route.hops[0].short_channel_id, 42);
                        assert_eq!(route.hops[0].fee_msat, 0);
                        assert_eq!(route.hops[0].cltv_expiry_delta, (8 << 8) | 1);
+                       assert_eq!(route.hops[0].node_features.le_flags(), &vec![0b11]);
+                       assert_eq!(route.hops[0].channel_features.le_flags(), &Vec::new()); // No feature flags will meet the relevant-to-channel conversion
 
                        assert_eq!(route.hops[1].pubkey, node7);
                        assert_eq!(route.hops[1].short_channel_id, 8);
                        assert_eq!(route.hops[1].fee_msat, 100);
                        assert_eq!(route.hops[1].cltv_expiry_delta, 42);
+                       assert_eq!(route.hops[1].node_features.le_flags(), &Vec::new()); // We dont pass flags in from invoices yet
+                       assert_eq!(route.hops[1].channel_features.le_flags(), &Vec::new()); // We can't learn any flags from invoices, sadly
                }
 
                last_hops[0].fee_base_msat = 1000;
@@ -1649,21 +1745,31 @@ mod tests {
                        assert_eq!(route.hops[0].short_channel_id, 2);
                        assert_eq!(route.hops[0].fee_msat, 200); // fee increased as its % of value transferred across node
                        assert_eq!(route.hops[0].cltv_expiry_delta, (4 << 8) | 1);
+                       assert_eq!(route.hops[0].node_features.le_flags(), &id_to_feature_flags!(2));
+                       assert_eq!(route.hops[0].channel_features.le_flags(), &id_to_feature_flags!(2));
 
                        assert_eq!(route.hops[1].pubkey, node3);
                        assert_eq!(route.hops[1].short_channel_id, 4);
                        assert_eq!(route.hops[1].fee_msat, 100);
                        assert_eq!(route.hops[1].cltv_expiry_delta, (7 << 8) | 1);
+                       assert_eq!(route.hops[1].node_features.le_flags(), &id_to_feature_flags!(3));
+                       assert_eq!(route.hops[1].channel_features.le_flags(), &id_to_feature_flags!(4));
 
                        assert_eq!(route.hops[2].pubkey, node6);
                        assert_eq!(route.hops[2].short_channel_id, 7);
                        assert_eq!(route.hops[2].fee_msat, 0);
                        assert_eq!(route.hops[2].cltv_expiry_delta, (10 << 8) | 1);
+                       // If we have a peer in the node map, we'll use their features here since we don't have
+                       // a way of figuring out their features from the invoice:
+                       assert_eq!(route.hops[2].node_features.le_flags(), &id_to_feature_flags!(6));
+                       assert_eq!(route.hops[2].channel_features.le_flags(), &id_to_feature_flags!(7));
 
                        assert_eq!(route.hops[3].pubkey, node7);
                        assert_eq!(route.hops[3].short_channel_id, 10);
                        assert_eq!(route.hops[3].fee_msat, 100);
                        assert_eq!(route.hops[3].cltv_expiry_delta, 42);
+                       assert_eq!(route.hops[3].node_features.le_flags(), &Vec::new()); // We dont pass flags in from invoices yet
+                       assert_eq!(route.hops[3].channel_features.le_flags(), &Vec::new()); // We can't learn any flags from invoices, sadly
                }
 
                { // ...but still use 8 for larger payments as 6 has a variable feerate
@@ -1674,26 +1780,38 @@ mod tests {
                        assert_eq!(route.hops[0].short_channel_id, 2);
                        assert_eq!(route.hops[0].fee_msat, 3000);
                        assert_eq!(route.hops[0].cltv_expiry_delta, (4 << 8) | 1);
+                       assert_eq!(route.hops[0].node_features.le_flags(), &id_to_feature_flags!(2));
+                       assert_eq!(route.hops[0].channel_features.le_flags(), &id_to_feature_flags!(2));
 
                        assert_eq!(route.hops[1].pubkey, node3);
                        assert_eq!(route.hops[1].short_channel_id, 4);
                        assert_eq!(route.hops[1].fee_msat, 0);
                        assert_eq!(route.hops[1].cltv_expiry_delta, (6 << 8) | 1);
+                       assert_eq!(route.hops[1].node_features.le_flags(), &id_to_feature_flags!(3));
+                       assert_eq!(route.hops[1].channel_features.le_flags(), &id_to_feature_flags!(4));
 
                        assert_eq!(route.hops[2].pubkey, node5);
                        assert_eq!(route.hops[2].short_channel_id, 6);
                        assert_eq!(route.hops[2].fee_msat, 0);
                        assert_eq!(route.hops[2].cltv_expiry_delta, (11 << 8) | 1);
+                       assert_eq!(route.hops[2].node_features.le_flags(), &id_to_feature_flags!(5));
+                       assert_eq!(route.hops[2].channel_features.le_flags(), &id_to_feature_flags!(6));
 
                        assert_eq!(route.hops[3].pubkey, node4);
                        assert_eq!(route.hops[3].short_channel_id, 11);
                        assert_eq!(route.hops[3].fee_msat, 1000);
                        assert_eq!(route.hops[3].cltv_expiry_delta, (8 << 8) | 1);
+                       // If we have a peer in the node map, we'll use their features here since we don't have
+                       // a way of figuring out their features from the invoice:
+                       assert_eq!(route.hops[3].node_features.le_flags(), &id_to_feature_flags!(4));
+                       assert_eq!(route.hops[3].channel_features.le_flags(), &id_to_feature_flags!(11));
 
                        assert_eq!(route.hops[4].pubkey, node7);
                        assert_eq!(route.hops[4].short_channel_id, 8);
                        assert_eq!(route.hops[4].fee_msat, 2000);
                        assert_eq!(route.hops[4].cltv_expiry_delta, 42);
+                       assert_eq!(route.hops[4].node_features.le_flags(), &Vec::new()); // We dont pass flags in from invoices yet
+                       assert_eq!(route.hops[4].channel_features.le_flags(), &Vec::new()); // We can't learn any flags from invoices, sadly
                }
 
                { // Test Router serialization/deserialization
index ee90fe7acf8ead65b3b7701f619d398db154f4fd..e5b5a3179665f874dfdbaaf628c9051a2dc1635e 100644 (file)
@@ -1,4 +1,4 @@
-use ln::chan_utils::{HTLCOutputInCommitment, TxCreationKeys};
+use ln::chan_utils::{HTLCOutputInCommitment, TxCreationKeys, ChannelPublicKeys};
 use ln::msgs;
 use chain::keysinterface::{ChannelKeys, InMemoryChannelKeys};
 
@@ -27,6 +27,27 @@ impl EnforcingChannelKeys {
                }
        }
 }
+
+impl EnforcingChannelKeys {
+       fn check_keys<T: secp256k1::Signing + secp256k1::Verification>(&self, secp_ctx: &Secp256k1<T>,
+                                                                      keys: &TxCreationKeys) {
+               let revocation_base = PublicKey::from_secret_key(secp_ctx, &self.inner.revocation_base_key);
+               let payment_base = PublicKey::from_secret_key(secp_ctx, &self.inner.payment_base_key);
+               let htlc_base = PublicKey::from_secret_key(secp_ctx, &self.inner.htlc_base_key);
+
+               let remote_points = self.inner.remote_channel_pubkeys.as_ref().unwrap();
+
+               let keys_expected = TxCreationKeys::new(secp_ctx,
+                                                       &keys.per_commitment_point,
+                                                       &remote_points.delayed_payment_basepoint,
+                                                       &remote_points.htlc_basepoint,
+                                                       &revocation_base,
+                                                       &payment_base,
+                                                       &htlc_base).unwrap();
+               if keys != &keys_expected { panic!("derived different per-tx keys") }
+       }
+}
+
 impl ChannelKeys for EnforcingChannelKeys {
        fn funding_key(&self) -> &SecretKey { self.inner.funding_key() }
        fn revocation_base_key(&self) -> &SecretKey { self.inner.revocation_base_key() }
@@ -35,8 +56,9 @@ impl ChannelKeys for EnforcingChannelKeys {
        fn htlc_base_key(&self) -> &SecretKey { self.inner.htlc_base_key() }
        fn commitment_seed(&self) -> &[u8; 32] { self.inner.commitment_seed() }
 
-       fn sign_remote_commitment<T: secp256k1::Signing>(&self, channel_value_satoshis: u64, feerate_per_kw: u64, commitment_tx: &Transaction, keys: &TxCreationKeys, htlcs: &[&HTLCOutputInCommitment], to_self_delay: u16, secp_ctx: &Secp256k1<T>) -> Result<(Signature, Vec<Signature>), ()> {
-               if commitment_tx.input.len() != 1 { panic!(); }
+       fn sign_remote_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, channel_value_satoshis: u64, feerate_per_kw: u64, commitment_tx: &Transaction, keys: &TxCreationKeys, htlcs: &[&HTLCOutputInCommitment], to_self_delay: u16, secp_ctx: &Secp256k1<T>) -> Result<(Signature, Vec<Signature>), ()> {
+               if commitment_tx.input.len() != 1 { panic!("lightning commitment transactions have a single input"); }
+               self.check_keys(secp_ctx, keys);
                let obscured_commitment_transaction_number = (commitment_tx.lock_time & 0xffffff) as u64 | ((commitment_tx.input[0].sequence as u64 & 0xffffff) << 3*8);
 
                {
@@ -60,11 +82,12 @@ impl ChannelKeys for EnforcingChannelKeys {
                self.inner.sign_channel_announcement(msg, secp_ctx)
        }
 
-       fn set_remote_funding_pubkey(&mut self, key: &PublicKey) {
-               self.inner.set_remote_funding_pubkey(key)
+       fn set_remote_channel_pubkeys(&mut self, channel_pubkeys: &ChannelPublicKeys) {
+               self.inner.set_remote_channel_pubkeys(channel_pubkeys)
        }
 }
 
+
 impl_writeable!(EnforcingChannelKeys, 0, {
        inner,
        commitment_number_obscure_and_last
index ef7fbd9bb6c299b556edd768c9794ad4c2a5961e..e3a431ed54f8614d988c8ad2654d7389d9ed1e59 100644 (file)
@@ -5,6 +5,7 @@ use bitcoin::blockdata::transaction::Transaction;
 use secp256k1::key::PublicKey;
 
 use ln::router::Route;
+use ln::chan_utils::HTLCType;
 
 use std;
 
@@ -93,15 +94,29 @@ macro_rules! log_route {
 pub(crate) struct DebugTx<'a>(pub &'a Transaction);
 impl<'a> std::fmt::Display for DebugTx<'a> {
        fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
-               if self.0.input.len() == 1 && self.0.input[0].witness.last().unwrap().len() == 71 && (self.0.input[0].sequence >> 8*3) as u8 == 0x80 { write!(f, "commitment tx")?; }
-               else if self.0.input.len() == 1 && self.0.input[0].witness.last().unwrap().len() == 71 { write!(f, "closing tx")?; }
-               else if self.0.input.len() == 1 && self.0.input[0].witness.last().unwrap().len() == 133 && self.0.input[0].witness.len() == 5 { write!(f, "HTLC-timeout tx")?; }
-               else if self.0.input.len() == 1 && (self.0.input[0].witness.last().unwrap().len() == 138 || self.0.input[0].witness.last().unwrap().len() == 139) && self.0.input[0].witness.len() == 5 { write!(f, "HTLC-success tx")?; }
-               else {
-                       for inp in &self.0.input {
-                               if inp.witness.last().unwrap().len() == 133 { write!(f, "preimage tx")?; break }
-                               else if inp.witness.last().unwrap().len() == 138 { write!(f, "timeout tx")?; break }
+               if self.0.input.len() >= 1 && self.0.input.iter().any(|i| !i.witness.is_empty()) {
+                       if self.0.input.len() == 1 && self.0.input[0].witness.last().unwrap().len() == 71 &&
+                                       (self.0.input[0].sequence >> 8*3) as u8 == 0x80 {
+                               write!(f, "commitment tx")?;
+                       } else if self.0.input.len() == 1 && self.0.input[0].witness.last().unwrap().len() == 71 {
+                               write!(f, "closing tx")?;
+                       } else if self.0.input.len() == 1 && HTLCType::scriptlen_to_htlctype(self.0.input[0].witness.last().unwrap().len()) == Some(HTLCType::OfferedHTLC) &&
+                                       self.0.input[0].witness.len() == 5 {
+                               write!(f, "HTLC-timeout tx")?;
+                       } else if self.0.input.len() == 1 && HTLCType::scriptlen_to_htlctype(self.0.input[0].witness.last().unwrap().len()) == Some(HTLCType::AcceptedHTLC) &&
+                                       self.0.input[0].witness.len() == 5 {
+                               write!(f, "HTLC-success tx")?;
+                       } else {
+                               for inp in &self.0.input {
+                                       if !inp.witness.is_empty() {
+                                               if HTLCType::scriptlen_to_htlctype(inp.witness.last().unwrap().len()) == Some(HTLCType::OfferedHTLC) { write!(f, "preimage-")?; break }
+                                               else if HTLCType::scriptlen_to_htlctype(inp.witness.last().unwrap().len()) == Some(HTLCType::AcceptedHTLC) { write!(f, "timeout-")?; break }
+                                       }
+                               }
+                               write!(f, "tx")?;
                        }
+               } else {
+                       write!(f, "INVALID TRANSACTION")?;
                }
                Ok(())
        }
index ebdbcc414ecaeae7bf920fcd69c14c5a47958426..6b3649bcf0ecc34075dffaa86b00f4982387a5dd 100644 (file)
@@ -117,7 +117,7 @@ impl msgs::ChannelMessageHandler for TestChannelMessageHandler {
        fn handle_announcement_signatures(&self, _their_node_id: &PublicKey, _msg: &msgs::AnnouncementSignatures) {}
        fn handle_channel_reestablish(&self, _their_node_id: &PublicKey, _msg: &msgs::ChannelReestablish) {}
        fn peer_disconnected(&self, _their_node_id: &PublicKey, _no_connection_possible: bool) {}
-       fn peer_connected(&self, _their_node_id: &PublicKey) {}
+       fn peer_connected(&self, _their_node_id: &PublicKey, _msg: &msgs::Init) {}
        fn handle_error(&self, _their_node_id: &PublicKey, _msg: &msgs::ErrorMessage) {}
 }