Use APIError::ChannelUnavailable a bit more for consistency
[rust-lightning] / src / ln / router.rs
index 9ef5b7a7ada8fcf617a63d9c5ac115323b003f82..4a55df88c6f90fd30d309e506377d819a7720a02 100644 (file)
@@ -1,11 +1,21 @@
+//! The top-level routing/network map tracking logic lives here.
+//!
+//! You probably want to create a Router and use that as your RoutingMessageHandler and then
+//! interrogate it to get routes for your own payments.
+
 use secp256k1::key::PublicKey;
 use secp256k1::{Secp256k1,Message};
+use secp256k1;
 
 use bitcoin::util::hash::Sha256dHash;
+use bitcoin::blockdata::script::Builder;
+use bitcoin::blockdata::opcodes;
 
+use chain::chaininterface::{ChainError, ChainWatchInterface};
 use ln::channelmanager;
-use ln::msgs::{ErrorAction,HandleError,RoutingMessageHandler,MsgEncodable,NetAddress,GlobalFeatures};
+use ln::msgs::{ErrorAction,HandleError,RoutingMessageHandler,NetAddress,GlobalFeatures};
 use ln::msgs;
+use util::ser::Writeable;
 use util::logger::Logger;
 
 use std::cmp;
@@ -17,6 +27,7 @@ use std;
 /// A hop in a route
 #[derive(Clone)]
 pub struct RouteHop {
+       /// The node_id of the node at this hop.
        pub pubkey: PublicKey,
        /// The channel that should be used from the previous hop to reach this node.
        pub short_channel_id: u64,
@@ -48,7 +59,7 @@ struct DirectionalChannelInfo {
 
 impl std::fmt::Display for DirectionalChannelInfo {
        fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
-               write!(f, " node id {} last_update {} enabled {} cltv_expiry_delta {} htlc_minimum_msat {} fee_base_msat {} fee_proportional_millionths {}\n", log_pubkey!(self.src_node_id), self.last_update, self.enabled, self.cltv_expiry_delta, self.htlc_minimum_msat, self.fee_base_msat, self.fee_proportional_millionths)?;
+               write!(f, "src_node_id {}, last_update {}, enabled {}, cltv_expiry_delta {}, htlc_minimum_msat {}, fee_base_msat {}, fee_proportional_millionths {}", log_pubkey!(self.src_node_id), self.last_update, self.enabled, self.cltv_expiry_delta, self.htlc_minimum_msat, self.fee_base_msat, self.fee_proportional_millionths)?;
                Ok(())
        }
 }
@@ -61,9 +72,7 @@ struct ChannelInfo {
 
 impl std::fmt::Display for ChannelInfo {
        fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
-               //TODO: GlobalFeatures
-               write!(f, " one_to_two {}", self.one_to_two)?;
-               write!(f, " two_to_one {}", self.two_to_one)?;
+               write!(f, "features: {}, one_to_two: {}, two_to_one: {}", log_bytes!(self.features.encode()), self.one_to_two, self.two_to_one)?;
                Ok(())
        }
 }
@@ -86,13 +95,7 @@ struct NodeInfo {
 
 impl std::fmt::Display for NodeInfo {
        fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
-               write!(f, " Channels\n")?;
-               for c in self.channels.iter() {
-                       write!(f, " {}\n", c)?;
-               }
-               write!(f, " lowest_inbound_channel_fee_base_msat {}\n", self.lowest_inbound_channel_fee_base_msat)?;
-               write!(f, " lowest_inbound_channel_fee_proportional_millionths {}\n", self.lowest_inbound_channel_fee_proportional_millionths)?;
-               //TODO: GlobalFeatures, last_update, rgb, alias, addresses
+               write!(f, "features: {}, last_update: {}, lowest_inbound_channel_fee_base_msat: {}, lowest_inbound_channel_fee_proportional_millionths: {}, channels: {:?}", log_bytes!(self.features.encode()), self.last_update, self.lowest_inbound_channel_fee_base_msat, self.lowest_inbound_channel_fee_proportional_millionths, &self.channels[..])?;
                Ok(())
        }
 }
@@ -106,16 +109,30 @@ struct NetworkMap {
        our_node_id: PublicKey,
        nodes: HashMap<PublicKey, NodeInfo>,
 }
-
+struct MutNetworkMap<'a> {
+       #[cfg(feature = "non_bitcoin_chain_hash_routing")]
+       channels: &'a mut HashMap<(u64, Sha256dHash), ChannelInfo>,
+       #[cfg(not(feature = "non_bitcoin_chain_hash_routing"))]
+       channels: &'a mut HashMap<u64, ChannelInfo>,
+       nodes: &'a mut HashMap<PublicKey, NodeInfo>,
+}
+impl NetworkMap {
+       fn borrow_parts(&mut self) -> MutNetworkMap {
+               MutNetworkMap {
+                       channels: &mut self.channels,
+                       nodes: &mut self.nodes,
+               }
+       }
+}
 impl std::fmt::Display for NetworkMap {
        fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
                write!(f, "Node id {} network map\n[Channels]\n", log_pubkey!(self.our_node_id))?;
                for (key, val) in self.channels.iter() {
-                       write!(f, " {} :\n {}\n", key, val)?;
+                       write!(f, " {}: {}\n", key, val)?;
                }
                write!(f, "[Nodes]\n")?;
                for (key, val) in self.nodes.iter() {
-                       write!(f, " {} :\n {}\n", log_pubkey!(key), val)?;
+                       write!(f, " {}: {}\n", log_pubkey!(key), val)?;
                }
                Ok(())
        }
@@ -149,19 +166,27 @@ impl NetworkMap {
 
 /// A channel descriptor which provides a last-hop route to get_route
 pub struct RouteHint {
+       /// The node_id of the non-target end of the route
        pub src_node_id: PublicKey,
+       /// The short_channel_id of this channel
        pub short_channel_id: u64,
+       /// The static msat-denominated fee which must be paid to use this channel
        pub fee_base_msat: u32,
+       /// The dynamic proportional fee which must be paid to use this channel, denominated in
+       /// millionths of the value being forwarded to the next hop.
        pub fee_proportional_millionths: u32,
+       /// The difference in CLTV values between this node and the next node.
        pub cltv_expiry_delta: u16,
+       /// The minimum value, in msat, which must be relayed to the next hop.
        pub htlc_minimum_msat: u64,
 }
 
 /// Tracks a view of the network, receiving updates from peers and generating Routes to
 /// payment destinations.
 pub struct Router {
-       secp_ctx: Secp256k1,
+       secp_ctx: Secp256k1<secp256k1::VerifyOnly>,
        network_map: RwLock<NetworkMap>,
+       chain_monitor: Arc<ChainWatchInterface>,
        logger: Arc<Logger>,
 }
 
@@ -175,10 +200,14 @@ macro_rules! secp_verify_sig {
 }
 
 impl RoutingMessageHandler for Router {
-       fn handle_node_announcement(&self, msg: &msgs::NodeAnnouncement) -> Result<(), HandleError> {
+       fn handle_node_announcement(&self, msg: &msgs::NodeAnnouncement) -> Result<bool, HandleError> {
                let msg_hash = Message::from_slice(&Sha256dHash::from_data(&msg.contents.encode()[..])[..]).unwrap();
                secp_verify_sig!(self.secp_ctx, &msg_hash, &msg.signature, &msg.contents.node_id);
 
+               if msg.contents.features.requires_unknown_bits() {
+                       panic!("Unknown-required-features NodeAnnouncements should never deserialize!");
+               }
+
                let mut network = self.network_map.write().unwrap();
                match network.nodes.get_mut(&msg.contents.node_id) {
                        None => Err(HandleError{err: "No existing channels for node_announcement", action: Some(ErrorAction::IgnoreError)}),
@@ -192,56 +221,98 @@ impl RoutingMessageHandler for Router {
                                node.rgb = msg.contents.rgb;
                                node.alias = msg.contents.alias;
                                node.addresses = msg.contents.addresses.clone();
-                               Ok(())
+                               Ok(msg.contents.excess_data.is_empty() && msg.contents.excess_address_data.is_empty() && !msg.contents.features.supports_unknown_bits())
                        }
                }
        }
 
        fn handle_channel_announcement(&self, msg: &msgs::ChannelAnnouncement) -> Result<bool, HandleError> {
+               if msg.contents.node_id_1 == msg.contents.node_id_2 || msg.contents.bitcoin_key_1 == msg.contents.bitcoin_key_2 {
+                       return Err(HandleError{err: "Channel announcement node had a channel with itself", action: Some(ErrorAction::IgnoreError)});
+               }
+
                let msg_hash = Message::from_slice(&Sha256dHash::from_data(&msg.contents.encode()[..])[..]).unwrap();
                secp_verify_sig!(self.secp_ctx, &msg_hash, &msg.node_signature_1, &msg.contents.node_id_1);
                secp_verify_sig!(self.secp_ctx, &msg_hash, &msg.node_signature_2, &msg.contents.node_id_2);
                secp_verify_sig!(self.secp_ctx, &msg_hash, &msg.bitcoin_signature_1, &msg.contents.bitcoin_key_1);
                secp_verify_sig!(self.secp_ctx, &msg_hash, &msg.bitcoin_signature_2, &msg.contents.bitcoin_key_2);
 
-               //TODO: Call blockchain thing to ask if the short_channel_id is valid
-               //TODO: Only allow bitcoin chain_hash
-
                if msg.contents.features.requires_unknown_bits() {
-                       return Err(HandleError{err: "Channel announcement required unknown feature flags", action: None});
+                       panic!("Unknown-required-features ChannelAnnouncements should never deserialize!");
                }
 
-               let mut network = self.network_map.write().unwrap();
+               let checked_utxo = match self.chain_monitor.get_chain_utxo(msg.contents.chain_hash, msg.contents.short_channel_id) {
+                       Ok((script_pubkey, _value)) => {
+                               let expected_script = Builder::new().push_opcode(opcodes::All::OP_PUSHNUM_2)
+                                                                   .push_slice(&msg.contents.bitcoin_key_1.serialize())
+                                                                   .push_slice(&msg.contents.bitcoin_key_2.serialize())
+                                                                   .push_opcode(opcodes::All::OP_PUSHNUM_2).push_opcode(opcodes::All::OP_CHECKMULTISIG).into_script().to_v0_p2wsh();
+                               if script_pubkey != expected_script {
+                                       return Err(HandleError{err: "Channel announcement keys didn't match on-chain script", action: Some(ErrorAction::IgnoreError)});
+                               }
+                               //TODO: Check if value is worth storing, use it to inform routing, and compare it
+                               //to the new HTLC max field in channel_update
+                               true
+                       },
+                       Err(ChainError::NotSupported) => {
+                               // Tentatively accept, potentially exposing us to DoS attacks
+                               false
+                       },
+                       Err(ChainError::NotWatched) => {
+                               return Err(HandleError{err: "Channel announced on an unknown chain", action: Some(ErrorAction::IgnoreError)});
+                       },
+                       Err(ChainError::UnknownTx) => {
+                               return Err(HandleError{err: "Channel announced without corresponding UTXO entry", action: Some(ErrorAction::IgnoreError)});
+                       },
+               };
+
+               let mut network_lock = self.network_map.write().unwrap();
+               let network = network_lock.borrow_parts();
+
+               let chan_info = ChannelInfo {
+                               features: msg.contents.features.clone(),
+                               one_to_two: DirectionalChannelInfo {
+                                       src_node_id: msg.contents.node_id_1.clone(),
+                                       last_update: 0,
+                                       enabled: false,
+                                       cltv_expiry_delta: u16::max_value(),
+                                       htlc_minimum_msat: u64::max_value(),
+                                       fee_base_msat: u32::max_value(),
+                                       fee_proportional_millionths: u32::max_value(),
+                               },
+                               two_to_one: DirectionalChannelInfo {
+                                       src_node_id: msg.contents.node_id_2.clone(),
+                                       last_update: 0,
+                                       enabled: false,
+                                       cltv_expiry_delta: u16::max_value(),
+                                       htlc_minimum_msat: u64::max_value(),
+                                       fee_base_msat: u32::max_value(),
+                                       fee_proportional_millionths: u32::max_value(),
+                               }
+                       };
 
                match network.channels.entry(NetworkMap::get_key(msg.contents.short_channel_id, msg.contents.chain_hash)) {
-                       Entry::Occupied(_) => {
+                       Entry::Occupied(mut entry) => {
                                //TODO: because asking the blockchain if short_channel_id is valid is only optional
                                //in the blockchain API, we need to handle it smartly here, though its unclear
                                //exactly how...
-                               return Err(HandleError{err: "Already have knowledge of channel", action: Some(ErrorAction::IgnoreError)})
+                               if checked_utxo {
+                                       // Either our UTXO provider is busted, there was a reorg, or the UTXO provider
+                                       // only sometimes returns results. In any case remove the previous entry. Note
+                                       // that the spec expects us to "blacklist" the node_ids involved, but we can't
+                                       // do that because
+                                       // a) we don't *require* a UTXO provider that always returns results.
+                                       // b) we don't track UTXOs of channels we know about and remove them if they
+                                       //    get reorg'd out.
+                                       // c) it's unclear how to do so without exposing ourselves to massive DoS risk.
+                                       Self::remove_channel_in_nodes(network.nodes, &entry.get(), msg.contents.short_channel_id);
+                                       *entry.get_mut() = chan_info;
+                               } else {
+                                       return Err(HandleError{err: "Already have knowledge of channel", action: Some(ErrorAction::IgnoreError)})
+                               }
                        },
                        Entry::Vacant(entry) => {
-                               entry.insert(ChannelInfo {
-                                       features: msg.contents.features.clone(),
-                                       one_to_two: DirectionalChannelInfo {
-                                               src_node_id: msg.contents.node_id_1.clone(),
-                                               last_update: 0,
-                                               enabled: false,
-                                               cltv_expiry_delta: u16::max_value(),
-                                               htlc_minimum_msat: u64::max_value(),
-                                               fee_base_msat: u32::max_value(),
-                                               fee_proportional_millionths: u32::max_value(),
-                                       },
-                                       two_to_one: DirectionalChannelInfo {
-                                               src_node_id: msg.contents.node_id_2.clone(),
-                                               last_update: 0,
-                                               enabled: false,
-                                               cltv_expiry_delta: u16::max_value(),
-                                               htlc_minimum_msat: u64::max_value(),
-                                               fee_base_msat: u32::max_value(),
-                                               fee_proportional_millionths: u32::max_value(),
-                                       }
-                               });
+                               entry.insert(chan_info);
                        }
                };
 
@@ -270,7 +341,7 @@ impl RoutingMessageHandler for Router {
                add_channel_to_node!(msg.contents.node_id_1);
                add_channel_to_node!(msg.contents.node_id_2);
 
-               Ok(!msg.contents.features.supports_unknown_bits())
+               Ok(msg.contents.excess_data.is_empty() && !msg.contents.features.supports_unknown_bits())
        }
 
        fn handle_htlc_fail_channel_update(&self, update: &msgs::HTLCFailChannelUpdate) {
@@ -281,18 +352,13 @@ impl RoutingMessageHandler for Router {
                        &msgs::HTLCFailChannelUpdate::ChannelClosed { ref short_channel_id } => {
                                let mut network = self.network_map.write().unwrap();
                                if let Some(chan) = network.channels.remove(short_channel_id) {
-                                       network.nodes.get_mut(&chan.one_to_two.src_node_id).unwrap().channels.retain(|chan_id| {
-                                               chan_id != NetworkMap::get_short_id(chan_id)
-                                       });
-                                       network.nodes.get_mut(&chan.two_to_one.src_node_id).unwrap().channels.retain(|chan_id| {
-                                               chan_id != NetworkMap::get_short_id(chan_id)
-                                       });
+                                       Self::remove_channel_in_nodes(&mut network.nodes, &chan, *short_channel_id);
                                }
                        },
                }
        }
 
-       fn handle_channel_update(&self, msg: &msgs::ChannelUpdate) -> Result<(), HandleError> {
+       fn handle_channel_update(&self, msg: &msgs::ChannelUpdate) -> Result<bool, HandleError> {
                let mut network = self.network_map.write().unwrap();
                let dest_node_id;
                let chan_enabled = msg.contents.flags & (1 << 1) != (1 << 1);
@@ -358,7 +424,7 @@ impl RoutingMessageHandler for Router {
                        mut_node.lowest_inbound_channel_fee_proportional_millionths = lowest_inbound_channel_fee_proportional_millionths;
                }
 
-               Ok(())
+               Ok(msg.contents.excess_data.is_empty())
        }
 }
 
@@ -391,7 +457,8 @@ struct DummyDirectionalChannelInfo {
 }
 
 impl Router {
-       pub fn new(our_pubkey: PublicKey, logger: Arc<Logger>) -> Router {
+       /// Creates a new router with the given node_id to be used as the source for get_route()
+       pub fn new(our_pubkey: PublicKey, chain_monitor: Arc<ChainWatchInterface>, logger: Arc<Logger>) -> Router {
                let mut nodes = HashMap::new();
                nodes.insert(our_pubkey.clone(), NodeInfo {
                        channels: Vec::new(),
@@ -404,16 +471,23 @@ impl Router {
                        addresses: Vec::new(),
                });
                Router {
-                       secp_ctx: Secp256k1::new(),
+                       secp_ctx: Secp256k1::verification_only(),
                        network_map: RwLock::new(NetworkMap {
                                channels: HashMap::new(),
                                our_node_id: our_pubkey,
                                nodes: nodes,
                        }),
+                       chain_monitor,
                        logger,
                }
        }
 
+       /// Dumps the entire network view of this Router to the logger provided in the constructor at
+       /// level Trace
+       pub fn trace_state(&self) {
+               log_trace!(self, "{}", self.network_map.read().unwrap());
+       }
+
        /// Get network addresses by node id
        pub fn get_addresses(&self, pubkey: &PublicKey) -> Option<Vec<NetAddress>> {
                let network = self.network_map.read().unwrap();
@@ -430,14 +504,38 @@ impl Router {
                unimplemented!();
        }
 
+       fn remove_channel_in_nodes(nodes: &mut HashMap<PublicKey, NodeInfo>, chan: &ChannelInfo, short_channel_id: u64) {
+               macro_rules! remove_from_node {
+                       ($node_id: expr) => {
+                               if let Entry::Occupied(mut entry) = nodes.entry($node_id) {
+                                       entry.get_mut().channels.retain(|chan_id| {
+                                               short_channel_id != *NetworkMap::get_short_id(chan_id)
+                                       });
+                                       if entry.get().channels.is_empty() {
+                                               entry.remove_entry();
+                                       }
+                               } else {
+                                       panic!("Had channel that pointed to unknown node (ie inconsistent network map)!");
+                               }
+                       }
+               }
+               remove_from_node!(chan.one_to_two.src_node_id);
+               remove_from_node!(chan.two_to_one.src_node_id);
+       }
+
        /// Gets a route from us to the given target node.
+       ///
        /// Extra routing hops between known nodes and the target will be used if they are included in
        /// last_hops.
+       ///
        /// If some channels aren't announced, it may be useful to fill in a first_hops with the
        /// results from a local ChannelManager::list_usable_channels() call. If it is filled in, our
        /// (this Router's) view of our local channels will be ignored, and only those in first_hops
-       /// will be used. Panics if first_hops contains channels without short_channel_ids
+       /// will be used.
+       ///
+       /// Panics if first_hops contains channels without short_channel_ids
        /// (ChannelManager::list_usable_channels will never include such channels).
+       ///
        /// The fees on channels from us to next-hops are ignored (as they are assumed to all be
        /// equal), however the enabled/disabled bit on such channels as well as the htlc_minimum_msat
        /// *is* checked as they may change based on the receiving node.
@@ -610,9 +708,9 @@ impl Router {
                                }
                                res.last_mut().unwrap().fee_msat = final_value_msat;
                                res.last_mut().unwrap().cltv_expiry_delta = final_cltv;
-                               return Ok(Route {
-                                       hops: res
-                               });
+                               let route = Route { hops: res };
+                               log_trace!(self, "Got route: {}", log_route!(route));
+                               return Ok(route);
                        }
 
                        match network.nodes.get(&pubkey) {
@@ -629,6 +727,7 @@ impl Router {
 
 #[cfg(test)]
 mod tests {
+       use chain::chaininterface;
        use ln::channelmanager;
        use ln::router::{Router,NodeInfo,NetworkMap,ChannelInfo,DirectionalChannelInfo,RouteHint};
        use ln::msgs::GlobalFeatures;
@@ -636,6 +735,7 @@ mod tests {
        use util::logger::Logger;
 
        use bitcoin::util::hash::Sha256dHash;
+       use bitcoin::network::constants::Network;
 
        use hex;
 
@@ -647,9 +747,10 @@ mod tests {
        #[test]
        fn route_test() {
                let secp_ctx = Secp256k1::new();
-               let our_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex::decode("0101010101010101010101010101010101010101010101010101010101010101").unwrap()[..]).unwrap()).unwrap();
+               let our_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex::decode("0101010101010101010101010101010101010101010101010101010101010101").unwrap()[..]).unwrap());
                let logger: Arc<Logger> = Arc::new(test_utils::TestLogger::new());
-               let router = Router::new(our_id, Arc::clone(&logger));
+               let chain_monitor = Arc::new(chaininterface::ChainWatchInterfaceUtil::new(Network::Testnet, Arc::clone(&logger)));
+               let router = Router::new(our_id, chain_monitor, Arc::clone(&logger));
 
                // Build network from our_id to node8:
                //
@@ -708,14 +809,14 @@ mod tests {
                // chan11 1-to-2: enabled, 0 fee
                // chan11 2-to-1: enabled, 0 fee
 
-               let node1 = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex::decode("0202020202020202020202020202020202020202020202020202020202020202").unwrap()[..]).unwrap()).unwrap();
-               let node2 = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex::decode("0303030303030303030303030303030303030303030303030303030303030303").unwrap()[..]).unwrap()).unwrap();
-               let node3 = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex::decode("0404040404040404040404040404040404040404040404040404040404040404").unwrap()[..]).unwrap()).unwrap();
-               let node4 = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex::decode("0505050505050505050505050505050505050505050505050505050505050505").unwrap()[..]).unwrap()).unwrap();
-               let node5 = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex::decode("0606060606060606060606060606060606060606060606060606060606060606").unwrap()[..]).unwrap()).unwrap();
-               let node6 = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex::decode("0707070707070707070707070707070707070707070707070707070707070707").unwrap()[..]).unwrap()).unwrap();
-               let node7 = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex::decode("0808080808080808080808080808080808080808080808080808080808080808").unwrap()[..]).unwrap()).unwrap();
-               let node8 = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex::decode("0909090909090909090909090909090909090909090909090909090909090909").unwrap()[..]).unwrap()).unwrap();
+               let node1 = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex::decode("0202020202020202020202020202020202020202020202020202020202020202").unwrap()[..]).unwrap());
+               let node2 = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex::decode("0303030303030303030303030303030303030303030303030303030303030303").unwrap()[..]).unwrap());
+               let node3 = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex::decode("0404040404040404040404040404040404040404040404040404040404040404").unwrap()[..]).unwrap());
+               let node4 = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex::decode("0505050505050505050505050505050505050505050505050505050505050505").unwrap()[..]).unwrap());
+               let node5 = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex::decode("0606060606060606060606060606060606060606060606060606060606060606").unwrap()[..]).unwrap());
+               let node6 = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex::decode("0707070707070707070707070707070707070707070707070707070707070707").unwrap()[..]).unwrap());
+               let node7 = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex::decode("0808080808080808080808080808080808080808080808080808080808080808").unwrap()[..]).unwrap());
+               let node8 = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex::decode("0909090909090909090909090909090909090909090909090909090909090909").unwrap()[..]).unwrap());
 
                let zero_hash = Sha256dHash::from_data(&[0; 32]);