X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Frouting%2Fnetwork_graph.rs;h=5003ca512f520df073c1b94e612ced49bb6b5ca1;hb=d9c03f26f9d52ca96bc889eae64087a690ff1a22;hp=44f2ed237bf9ef9730ed5c8a0ea9da7db133a1fc;hpb=bce202536d0de69cc12b833fa9c7bc9cbba94b93;p=rust-lightning diff --git a/lightning/src/routing/network_graph.rs b/lightning/src/routing/network_graph.rs index 44f2ed23..5003ca51 100644 --- a/lightning/src/routing/network_graph.rs +++ b/lightning/src/routing/network_graph.rs @@ -16,9 +16,11 @@ use bitcoin::secp256k1; use bitcoin::hashes::sha256d::Hash as Sha256dHash; use bitcoin::hashes::Hash; use bitcoin::blockdata::script::Builder; +use bitcoin::blockdata::transaction::TxOut; use bitcoin::blockdata::opcodes; -use chain::chaininterface::{ChainError, ChainWatchInterface}; +use chain; +use chain::Access; use ln::features::{ChannelFeatures, NodeFeatures}; use ln::msgs::{DecodeError, ErrorAction, LightningError, RoutingMessageHandler, NetAddress, MAX_VALUE_MSAT}; use ln::msgs::{ChannelAnnouncement, ChannelUpdate, NodeAnnouncement, OptionalField}; @@ -27,7 +29,7 @@ use util::ser::{Writeable, Readable, Writer}; use util::logger::Logger; use std::{cmp, fmt}; -use std::sync::RwLock; +use std::sync::{RwLock, RwLockReadGuard}; use std::sync::atomic::{AtomicUsize, Ordering}; use std::collections::BTreeMap; use std::collections::btree_map::Entry as BtreeEntry; @@ -41,27 +43,32 @@ pub struct NetworkGraph { nodes: BTreeMap, } +/// A simple newtype for RwLockReadGuard<'a, NetworkGraph>. +/// This exists only to make accessing a RwLock possible from +/// the C bindings, as it can be done directly in Rust code. +pub struct LockedNetworkGraph<'a>(pub RwLockReadGuard<'a, NetworkGraph>); + /// Receives and validates network updates from peers, /// stores authentic and relevant data as a network graph. /// This network graph is then used for routing payments. /// Provides interface to help with initial routing sync by /// serving historical announcements. -pub struct NetGraphMsgHandler where C::Target: ChainWatchInterface, L::Target: Logger { +pub struct NetGraphMsgHandler where C::Target: chain::Access, L::Target: Logger { secp_ctx: Secp256k1, /// Representation of the payment channel network pub network_graph: RwLock, - chain_monitor: C, + chain_access: Option, full_syncs_requested: AtomicUsize, logger: L, } -impl NetGraphMsgHandler where C::Target: ChainWatchInterface, L::Target: Logger { +impl NetGraphMsgHandler where C::Target: chain::Access, L::Target: Logger { /// Creates a new tracker of the actual state of the network of channels and nodes, /// assuming a fresh network graph. /// Chain monitor is used to make sure announced channels exist on-chain, /// channel data is correct, and that the announcement is signed with /// channel owners' keys. - pub fn new(chain_monitor: C, logger: L) -> Self { + pub fn new(chain_access: Option, logger: L) -> Self { NetGraphMsgHandler { secp_ctx: Secp256k1::verification_only(), network_graph: RwLock::new(NetworkGraph { @@ -69,22 +76,37 @@ impl NetGraphMsgHandler where C::Target: ChainWatchInt nodes: BTreeMap::new(), }), full_syncs_requested: AtomicUsize::new(0), - chain_monitor, + chain_access, logger, } } /// Creates a new tracker of the actual state of the network of channels and nodes, /// assuming an existing Network Graph. - pub fn from_net_graph(chain_monitor: C, logger: L, network_graph: NetworkGraph) -> Self { + pub fn from_net_graph(chain_access: Option, logger: L, network_graph: NetworkGraph) -> Self { NetGraphMsgHandler { secp_ctx: Secp256k1::verification_only(), network_graph: RwLock::new(network_graph), full_syncs_requested: AtomicUsize::new(0), - chain_monitor, + chain_access, logger, } } + + /// Take a read lock on the network_graph and return it in the C-bindings + /// newtype helper. This is likely only useful when called via the C + /// bindings as you can call `self.network_graph.read().unwrap()` in Rust + /// yourself. + pub fn read_locked_graph<'a>(&'a self) -> LockedNetworkGraph<'a> { + LockedNetworkGraph(self.network_graph.read().unwrap()) + } +} + +impl<'a> LockedNetworkGraph<'a> { + /// Get a reference to the NetworkGraph which this read-lock contains. + pub fn graph(&self) -> &NetworkGraph { + &*self.0 + } } @@ -97,42 +119,13 @@ macro_rules! secp_verify_sig { }; } -impl RoutingMessageHandler for NetGraphMsgHandler where C::Target: ChainWatchInterface, L::Target: Logger { +impl RoutingMessageHandler for NetGraphMsgHandler where C::Target: chain::Access, L::Target: Logger { fn handle_node_announcement(&self, msg: &msgs::NodeAnnouncement) -> Result { self.network_graph.write().unwrap().update_node_from_announcement(msg, Some(&self.secp_ctx)) } fn handle_channel_announcement(&self, msg: &msgs::ChannelAnnouncement) -> Result { - if msg.contents.node_id_1 == msg.contents.node_id_2 || msg.contents.bitcoin_key_1 == msg.contents.bitcoin_key_2 { - return Err(LightningError{err: "Channel announcement node had a channel with itself".to_owned(), action: ErrorAction::IgnoreError}); - } - - let utxo_value = match self.chain_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(LightningError{err: format!("Channel announcement key ({}) didn't match on-chain script ({})", script_pubkey.to_hex(), expected_script.to_hex()), action: ErrorAction::IgnoreError}); - } - //TODO: Check if value is worth storing, use it to inform routing, and compare it - //to the new HTLC max field in channel_update - Some(value) - }, - Err(ChainError::NotSupported) => { - // Tentatively accept, potentially exposing us to DoS attacks - None - }, - Err(ChainError::NotWatched) => { - return Err(LightningError{err: format!("Channel announced on an unknown chain ({})", msg.contents.chain_hash.encode().to_hex()), action: ErrorAction::IgnoreError}); - }, - Err(ChainError::UnknownTx) => { - return Err(LightningError{err: "Channel announced without corresponding UTXO entry".to_owned(), action: ErrorAction::IgnoreError}); - }, - }; - let result = self.network_graph.write().unwrap().update_channel_from_announcement(msg, utxo_value, Some(&self.secp_ctx)); + let result = self.network_graph.write().unwrap().update_channel_from_announcement(msg, &self.chain_access, Some(&self.secp_ctx)); log_trace!(self.logger, "Added channel_announcement for {}{}", msg.contents.short_channel_id, if !msg.contents.excess_data.is_empty() { " with excess uninterpreted data!" } else { "" }); result } @@ -240,7 +233,7 @@ pub struct DirectionalChannelInfo { /// Mostly redundant with the data we store in fields explicitly. /// Everything else is useful only for sending out for initial routing sync. /// Not stored if contains excess data to prevent DoS. - pub last_update_message: Option, + pub last_update_message: Option, } impl fmt::Display for DirectionalChannelInfo { @@ -280,7 +273,7 @@ pub struct ChannelInfo { /// Mostly redundant with the data we store in fields explicitly. /// Everything else is useful only for sending out for initial routing sync. /// Not stored if contains excess data to prevent DoS. - pub announcement_message: Option, + pub announcement_message: Option, } impl fmt::Display for ChannelInfo { @@ -351,7 +344,7 @@ pub struct NodeAnnouncementInfo { /// Mostly redundant with the data we store in fields explicitly. /// Everything else is useful only for sending out for initial routing sync. /// Not stored if contains excess data to prevent DoS. - pub announcement_message: Option + pub announcement_message: Option } impl Writeable for NodeAnnouncementInfo { @@ -492,13 +485,13 @@ impl Readable for NetworkGraph { impl fmt::Display for NetworkGraph { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - write!(f, "Network map\n[Channels]\n")?; + writeln!(f, "Network map\n[Channels]")?; for (key, val) in self.channels.iter() { - write!(f, " {}: {}\n", key, val)?; + writeln!(f, " {}: {}", key, val)?; } - write!(f, "[Nodes]\n")?; + writeln!(f, "[Nodes]")?; for (key, val) in self.nodes.iter() { - write!(f, " {}: {}\n", log_pubkey!(key), val)?; + writeln!(f, " {}: {}", log_pubkey!(key), val)?; } Ok(()) } @@ -506,13 +499,19 @@ impl fmt::Display for NetworkGraph { impl NetworkGraph { /// Returns all known valid channels' short ids along with announced channel info. + /// + /// (C-not exported) because we have no mapping for `BTreeMap`s pub fn get_channels<'a>(&'a self) -> &'a BTreeMap { &self.channels } /// Returns all known nodes' public keys along with announced node info. + /// + /// (C-not exported) because we have no mapping for `BTreeMap`s pub fn get_nodes<'a>(&'a self) -> &'a BTreeMap { &self.nodes } /// Get network addresses by node id. /// Returns None if the requested node is completely unknown, /// or if node announcement for the node was never received. + /// + /// (C-not exported) as there is no practical way to track lifetimes of returned values. pub fn get_addresses<'a>(&'a self, pubkey: &PublicKey) -> Option<&'a Vec> { if let Some(node) = self.nodes.get(pubkey) { if let Some(node_info) = node.announcement_info.as_ref() { @@ -530,9 +529,14 @@ impl NetworkGraph { } } - /// For an already known node (from channel announcements), update its stored properties from a given node announcement + /// For an already known node (from channel announcements), update its stored properties from a given node announcement. + /// + /// You probably don't want to call this directly, instead relying on a NetGraphMsgHandler's + /// RoutingMessageHandler implementation to call it indirectly. This may be useful to accept + /// routing messages without checking their signatures. + /// /// Announcement signatures are checked here only if Secp256k1 object is provided. - fn update_node_from_announcement(&mut self, msg: &msgs::NodeAnnouncement, secp_ctx: Option<&Secp256k1>) -> Result { + pub fn update_node_from_announcement(&mut self, msg: &msgs::NodeAnnouncement, secp_ctx: Option<&Secp256k1>) -> Result { if let Some(sig_verifier) = secp_ctx { let msg_hash = hash_to_message!(&Sha256dHash::hash(&msg.contents.encode()[..])[..]); secp_verify_sig!(sig_verifier, &msg_hash, &msg.signature, &msg.contents.node_id); @@ -562,13 +566,24 @@ impl NetworkGraph { } } - /// For a new or already known (from previous announcement) channel, store or update channel info. - /// Also store nodes (if not stored yet) the channel is between, and make node aware of this channel. - /// Checking utxo on-chain is useful if we receive an update for already known channel id, - /// which is probably result of a reorg. In that case, we update channel info only if the - /// utxo was checked, otherwise stick to the existing update, to prevent DoS risks. + /// Store or update channel info from a channel announcement. + /// + /// You probably don't want to call this directly, instead relying on a NetGraphMsgHandler's + /// RoutingMessageHandler implementation to call it indirectly. This may be useful to accept + /// routing messages without checking their signatures. + /// + /// If a `chain::Access` object is provided via `chain_access`, it will be called to verify + /// the corresponding UTXO exists on chain and is correctly-formatted. + /// /// Announcement signatures are checked here only if Secp256k1 object is provided. - fn update_channel_from_announcement(&mut self, msg: &msgs::ChannelAnnouncement, utxo_value: Option, secp_ctx: Option<&Secp256k1>) -> Result { + pub fn update_channel_from_announcement + (&mut self, msg: &msgs::ChannelAnnouncement, chain_access: &Option, secp_ctx: Option<&Secp256k1>) + -> Result + where C::Target: chain::Access { + if msg.contents.node_id_1 == msg.contents.node_id_2 || msg.contents.bitcoin_key_1 == msg.contents.bitcoin_key_2 { + return Err(LightningError{err: "Channel announcement node had a channel with itself".to_owned(), action: ErrorAction::IgnoreError}); + } + if let Some(sig_verifier) = secp_ctx { let msg_hash = hash_to_message!(&Sha256dHash::hash(&msg.contents.encode()[..])[..]); secp_verify_sig!(sig_verifier, &msg_hash, &msg.node_signature_1, &msg.contents.node_id_1); @@ -577,8 +592,37 @@ impl NetworkGraph { secp_verify_sig!(sig_verifier, &msg_hash, &msg.bitcoin_signature_2, &msg.contents.bitcoin_key_2); } - let should_relay = msg.contents.excess_data.is_empty(); + let utxo_value = match &chain_access { + &None => { + // Tentatively accept, potentially exposing us to DoS attacks + None + }, + &Some(ref chain_access) => { + match chain_access.get_utxo(&msg.contents.chain_hash, msg.contents.short_channel_id) { + Ok(TxOut { value, script_pubkey }) => { + let expected_script = Builder::new().push_opcode(opcodes::all::OP_PUSHNUM_2) + .push_slice(&msg.contents.bitcoin_key_1.serialize()) + .push_slice(&msg.contents.bitcoin_key_2.serialize()) + .push_opcode(opcodes::all::OP_PUSHNUM_2) + .push_opcode(opcodes::all::OP_CHECKMULTISIG).into_script().to_v0_p2wsh(); + if script_pubkey != expected_script { + return Err(LightningError{err: format!("Channel announcement key ({}) didn't match on-chain script ({})", script_pubkey.to_hex(), expected_script.to_hex()), action: ErrorAction::IgnoreError}); + } + //TODO: Check if value is worth storing, use it to inform routing, and compare it + //to the new HTLC max field in channel_update + Some(value) + }, + Err(chain::AccessError::UnknownChain) => { + return Err(LightningError{err: format!("Channel announced on an unknown chain ({})", msg.contents.chain_hash.encode().to_hex()), action: ErrorAction::IgnoreError}); + }, + Err(chain::AccessError::UnknownTx) => { + return Err(LightningError{err: "Channel announced without corresponding UTXO entry".to_owned(), action: ErrorAction::IgnoreError}); + }, + } + }, + }; + let should_relay = msg.contents.excess_data.is_empty(); let chan_info = ChannelInfo { features: msg.contents.features.clone(), node_one: msg.contents.node_id_1.clone(), @@ -667,8 +711,13 @@ impl NetworkGraph { } /// For an already known (from announcement) channel, update info about one of the directions of a channel. + /// + /// You probably don't want to call this directly, instead relying on a NetGraphMsgHandler's + /// RoutingMessageHandler implementation to call it indirectly. This may be useful to accept + /// routing messages without checking their signatures. + /// /// Announcement signatures are checked here only if Secp256k1 object is provided. - fn update_channel(&mut self, msg: &msgs::ChannelUpdate, secp_ctx: Option<&Secp256k1>) -> Result { + pub fn update_channel(&mut self, msg: &msgs::ChannelUpdate, secp_ctx: Option<&Secp256k1>) -> Result { let dest_node_id; let chan_enabled = msg.contents.flags & (1 << 1) != (1 << 1); let chan_was_enabled; @@ -684,8 +733,8 @@ impl NetworkGraph { if let Some(capacity_sats) = channel.capacity_sats { // It's possible channel capacity is available now, although it wasn't available at announcement (so the field is None). // Don't query UTXO set here to reduce DoS risks. - if htlc_maximum_msat > capacity_sats * 1000 { - return Err(LightningError{err: "htlc_maximum_msat is larger than channel capacity".to_owned(), action: ErrorAction::IgnoreError}); + if capacity_sats > MAX_VALUE_MSAT / 1000 || htlc_maximum_msat > capacity_sats * 1000 { + return Err(LightningError{err: "htlc_maximum_msat is larger than channel capacity or capacity is bogus".to_owned(), action: ErrorAction::IgnoreError}); } } } @@ -802,7 +851,7 @@ impl NetworkGraph { #[cfg(test)] mod tests { - use chain::chaininterface; + use chain; use ln::features::{ChannelFeatures, NodeFeatures}; use routing::network_graph::{NetGraphMsgHandler, NetworkGraph}; use ln::msgs::{OptionalField, RoutingMessageHandler, UnsignedNodeAnnouncement, NodeAnnouncement, @@ -817,8 +866,8 @@ mod tests { use bitcoin::network::constants::Network; use bitcoin::blockdata::constants::genesis_block; use bitcoin::blockdata::script::Builder; + use bitcoin::blockdata::transaction::TxOut; use bitcoin::blockdata::opcodes; - use bitcoin::util::hash::BitcoinHash; use hex; @@ -827,11 +876,10 @@ mod tests { use std::sync::Arc; - fn create_net_graph_msg_handler() -> (Secp256k1, NetGraphMsgHandler, Arc>) { + fn create_net_graph_msg_handler() -> (Secp256k1, NetGraphMsgHandler, Arc>) { let secp_ctx = Secp256k1::new(); let logger = Arc::new(test_utils::TestLogger::new()); - let chain_monitor = Arc::new(chaininterface::ChainWatchInterfaceUtil::new(Network::Testnet)); - let net_graph_msg_handler = NetGraphMsgHandler::new(chain_monitor, Arc::clone(&logger)); + let net_graph_msg_handler = NetGraphMsgHandler::new(None, Arc::clone(&logger)); (secp_ctx, net_graph_msg_handler) } @@ -886,7 +934,7 @@ mod tests { // Announce a channel to add a corresponding node. let unsigned_announcement = UnsignedChannelAnnouncement { features: ChannelFeatures::known(), - chain_hash: genesis_block(Network::Testnet).header.bitcoin_hash(), + chain_hash: genesis_block(Network::Testnet).header.block_hash(), short_channel_id: 0, node_id_1, node_id_2, @@ -956,9 +1004,6 @@ mod tests { fn handling_channel_announcements() { let secp_ctx = Secp256k1::new(); let logger: Arc = Arc::new(test_utils::TestLogger::new()); - let chain_monitor = Arc::new(test_utils::TestChainWatcher::new()); - let net_graph_msg_handler = NetGraphMsgHandler::new(chain_monitor.clone(), Arc::clone(&logger)); - let node_1_privkey = &SecretKey::from_slice(&[42; 32]).unwrap(); let node_2_privkey = &SecretKey::from_slice(&[41; 32]).unwrap(); @@ -976,7 +1021,7 @@ mod tests { let mut unsigned_announcement = UnsignedChannelAnnouncement { features: ChannelFeatures::known(), - chain_hash: genesis_block(Network::Testnet).header.bitcoin_hash(), + chain_hash: genesis_block(Network::Testnet).header.block_hash(), short_channel_id: 0, node_id_1, node_id_2, @@ -995,8 +1040,7 @@ mod tests { }; // Test if the UTXO lookups were not supported - *chain_monitor.utxo_ret.lock().unwrap() = Err(chaininterface::ChainError::NotSupported); - + let mut net_graph_msg_handler = NetGraphMsgHandler::new(None, Arc::clone(&logger)); match net_graph_msg_handler.handle_channel_announcement(&valid_announcement) { Ok(res) => assert!(res), _ => panic!() @@ -1010,7 +1054,6 @@ mod tests { } } - // If we receive announcement for the same channel (with UTXO lookups disabled), // drop new one on the floor, since we can't see any changes. match net_graph_msg_handler.handle_channel_announcement(&valid_announcement) { @@ -1018,9 +1061,10 @@ mod tests { Err(e) => assert_eq!(e.err, "Already have knowledge of channel") }; - // Test if an associated transaction were not on-chain (or not confirmed). - *chain_monitor.utxo_ret.lock().unwrap() = Err(chaininterface::ChainError::UnknownTx); + let chain_source = Arc::new(test_utils::TestChainSource::new(Network::Testnet)); + *chain_source.utxo_ret.lock().unwrap() = Err(chain::AccessError::UnknownTx); + net_graph_msg_handler = NetGraphMsgHandler::new(Some(chain_source.clone()), Arc::clone(&logger)); unsigned_announcement.short_channel_id += 1; msghash = hash_to_message!(&Sha256dHash::hash(&unsigned_announcement.encode()[..])[..]); @@ -1037,10 +1081,9 @@ mod tests { Err(e) => assert_eq!(e.err, "Channel announced without corresponding UTXO entry") }; - // Now test if the transaction is found in the UTXO set and the script is correct. unsigned_announcement.short_channel_id += 1; - *chain_monitor.utxo_ret.lock().unwrap() = Ok((good_script.clone(), 0)); + *chain_source.utxo_ret.lock().unwrap() = Ok(TxOut { value: 0, script_pubkey: good_script.clone() }); msghash = hash_to_message!(&Sha256dHash::hash(&unsigned_announcement.encode()[..])[..]); let valid_announcement = ChannelAnnouncement { @@ -1065,14 +1108,14 @@ mod tests { // If we receive announcement for the same channel (but TX is not confirmed), // drop new one on the floor, since we can't see any changes. - *chain_monitor.utxo_ret.lock().unwrap() = Err(chaininterface::ChainError::UnknownTx); + *chain_source.utxo_ret.lock().unwrap() = Err(chain::AccessError::UnknownTx); match net_graph_msg_handler.handle_channel_announcement(&valid_announcement) { Ok(_) => panic!(), Err(e) => assert_eq!(e.err, "Channel announced without corresponding UTXO entry") }; // But if it is confirmed, replace the channel - *chain_monitor.utxo_ret.lock().unwrap() = Ok((good_script, 0)); + *chain_source.utxo_ret.lock().unwrap() = Ok(TxOut { value: 0, script_pubkey: good_script }); unsigned_announcement.features = ChannelFeatures::empty(); msghash = hash_to_message!(&Sha256dHash::hash(&unsigned_announcement.encode()[..])[..]); let valid_announcement = ChannelAnnouncement { @@ -1144,8 +1187,8 @@ mod tests { fn handling_channel_update() { let secp_ctx = Secp256k1::new(); let logger: Arc = Arc::new(test_utils::TestLogger::new()); - let chain_monitor = Arc::new(test_utils::TestChainWatcher::new()); - let net_graph_msg_handler = NetGraphMsgHandler::new(chain_monitor.clone(), Arc::clone(&logger)); + let chain_source = Arc::new(test_utils::TestChainSource::new(Network::Testnet)); + let net_graph_msg_handler = NetGraphMsgHandler::new(Some(chain_source.clone()), Arc::clone(&logger)); let node_1_privkey = &SecretKey::from_slice(&[42; 32]).unwrap(); let node_2_privkey = &SecretKey::from_slice(&[41; 32]).unwrap(); @@ -1156,7 +1199,7 @@ mod tests { let zero_hash = Sha256dHash::hash(&[0; 32]); let short_channel_id = 0; - let chain_hash = genesis_block(Network::Testnet).header.bitcoin_hash(); + let chain_hash = genesis_block(Network::Testnet).header.block_hash(); let amount_sats = 1000_000; { @@ -1166,7 +1209,7 @@ mod tests { .push_slice(&PublicKey::from_secret_key(&secp_ctx, node_2_btckey).serialize()) .push_opcode(opcodes::all::OP_PUSHNUM_2) .push_opcode(opcodes::all::OP_CHECKMULTISIG).into_script().to_v0_p2wsh(); - *chain_monitor.utxo_ret.lock().unwrap() = Ok((good_script.clone(), amount_sats)); + *chain_source.utxo_ret.lock().unwrap() = Ok(TxOut { value: amount_sats, script_pubkey: good_script.clone() }); let unsigned_announcement = UnsignedChannelAnnouncement { features: ChannelFeatures::empty(), chain_hash, @@ -1276,7 +1319,7 @@ mod tests { match net_graph_msg_handler.handle_channel_update(&valid_channel_update) { Ok(_) => panic!(), - Err(e) => assert_eq!(e.err, "htlc_maximum_msat is larger than channel capacity") + Err(e) => assert_eq!(e.err, "htlc_maximum_msat is larger than channel capacity or capacity is bogus") }; unsigned_channel_update.htlc_maximum_msat = OptionalField::Absent; @@ -1319,7 +1362,7 @@ mod tests { let node_2_btckey = &SecretKey::from_slice(&[39; 32]).unwrap(); let short_channel_id = 0; - let chain_hash = genesis_block(Network::Testnet).header.bitcoin_hash(); + let chain_hash = genesis_block(Network::Testnet).header.block_hash(); { // There is no nodes in the table at the beginning. @@ -1434,7 +1477,7 @@ mod tests { let node_2_btckey = &SecretKey::from_slice(&[39; 32]).unwrap(); let short_channel_id = 1; - let chain_hash = genesis_block(Network::Testnet).header.bitcoin_hash(); + let chain_hash = genesis_block(Network::Testnet).header.block_hash(); // Channels were not announced yet. let channels_with_announcements = net_graph_msg_handler.get_next_channel_announcements(0, 1); @@ -1568,7 +1611,7 @@ mod tests { let node_2_btckey = &SecretKey::from_slice(&[39; 32]).unwrap(); let short_channel_id = 1; - let chain_hash = genesis_block(Network::Testnet).header.bitcoin_hash(); + let chain_hash = genesis_block(Network::Testnet).header.block_hash(); // No nodes yet. let next_announcements = net_graph_msg_handler.get_next_node_announcements(None, 10); @@ -1688,7 +1731,7 @@ mod tests { let node_id_2 = PublicKey::from_secret_key(&secp_ctx, node_2_privkey); let unsigned_announcement = UnsignedChannelAnnouncement { features: ChannelFeatures::known(), - chain_hash: genesis_block(Network::Testnet).header.bitcoin_hash(), + chain_hash: genesis_block(Network::Testnet).header.block_hash(), short_channel_id: 0, node_id_1, node_id_2,