X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;ds=sidebyside;f=lightning%2Fsrc%2Frouting%2Futxo.rs;h=e775e2628f6ca1df9e497a084506be7dd7eed6eb;hb=ae0d825d89ca0ac2489737d1b413e778650b093c;hp=0e5bd8d64f78a48a9ec5b808aa200a022167edb6;hpb=2c3e12e30925b007b7eec235b29236171ad2ed0e;p=rust-lightning diff --git a/lightning/src/routing/utxo.rs b/lightning/src/routing/utxo.rs index 0e5bd8d6..e775e262 100644 --- a/lightning/src/routing/utxo.rs +++ b/lightning/src/routing/utxo.rs @@ -13,20 +13,21 @@ //! channel matches a UTXO on-chain, requiring at least some marginal on-chain transacting in //! order to announce a channel. This module handles that checking. -use bitcoin::{BlockHash, TxOut}; -use bitcoin::hashes::hex::ToHex; +use bitcoin::TxOut; +use bitcoin::blockdata::constants::ChainHash; +use hex::DisplayHex; + +use crate::events::MessageSendEvent; use crate::ln::chan_utils::make_funding_redeemscript_from_slices; use crate::ln::msgs::{self, LightningError, ErrorAction}; use crate::routing::gossip::{NetworkGraph, NodeId, P2PGossipSync}; -use crate::util::events::MessageSendEvent; use crate::util::logger::{Level, Logger}; -use crate::util::ser::Writeable; use crate::prelude::*; use alloc::sync::{Arc, Weak}; -use crate::sync::Mutex; +use crate::sync::{Mutex, LockTestExt}; use core::ops::Deref; /// An error when accessing the chain via [`UtxoLookup`]. @@ -60,11 +61,11 @@ pub enum UtxoResult { /// The `UtxoLookup` trait defines behavior for accessing on-chain UTXOs. pub trait UtxoLookup { /// Returns the transaction output of a funding transaction encoded by [`short_channel_id`]. - /// Returns an error if `genesis_hash` is for a different chain or if such a transaction output - /// is unknown. + /// Returns an error if `chain_hash` is for a different chain or if such a transaction output is + /// unknown. /// /// [`short_channel_id`]: https://github.com/lightning/bolts/blob/master/07-routing-gossip.md#definition-of-short_channel_id - fn get_utxo(&self, genesis_hash: &BlockHash, short_channel_id: u64) -> UtxoResult; + fn get_utxo(&self, chain_hash: &ChainHash, short_channel_id: u64) -> UtxoResult; } enum ChannelAnnouncement { @@ -125,9 +126,9 @@ pub struct UtxoFuture { /// A trivial implementation of [`UtxoLookup`] which is used to call back into the network graph /// once we have a concrete resolution of a request. -struct UtxoResolver(Result); +pub(crate) struct UtxoResolver(Result); impl UtxoLookup for UtxoResolver { - fn get_utxo(&self, _genesis_hash: &BlockHash, _short_channel_id: u64) -> UtxoResult { + fn get_utxo(&self, _chain_hash: &ChainHash, _short_channel_id: u64) -> UtxoResult { UtxoResult::Sync(self.0.clone()) } } @@ -306,7 +307,7 @@ pub(super) struct PendingChecks { impl PendingChecks { pub(super) fn new() -> Self { PendingChecks { internal: Mutex::new(PendingChecksContext { - channels: HashMap::new(), nodes: HashMap::new(), + channels: new_hash_map(), nodes: new_hash_map(), }) } } @@ -404,7 +405,10 @@ impl PendingChecks { // lookup if we haven't gotten that far yet). match Weak::upgrade(&e.get()) { Some(pending_msgs) => { - let pending_matches = match &pending_msgs.lock().unwrap().channel_announce { + // This may be called with the mutex held on a different UtxoMessages + // struct, however in that case we have a global lockorder of new messages + // -> old messages, which makes this safe. + let pending_matches = match &pending_msgs.unsafe_well_ordered_double_lock_self().channel_announce { Some(ChannelAnnouncement::Full(pending_msg)) => Some(pending_msg) == full_msg, Some(ChannelAnnouncement::Unsigned(pending_msg)) => pending_msg == msg, None => { @@ -456,11 +460,11 @@ impl PendingChecks { match res { Ok(TxOut { value, script_pubkey }) => { let expected_script = - make_funding_redeemscript_from_slices(msg.bitcoin_key_1.as_slice(), msg.bitcoin_key_2.as_slice()).to_v0_p2wsh(); + make_funding_redeemscript_from_slices(msg.bitcoin_key_1.as_array(), msg.bitcoin_key_2.as_array()).to_v0_p2wsh(); if script_pubkey != expected_script { return Err(LightningError{ err: format!("Channel announcement key ({}) didn't match on-chain script ({})", - expected_script.to_hex(), script_pubkey.to_hex()), + expected_script.to_hex_string(), script_pubkey.to_hex_string()), action: ErrorAction::IgnoreError }); } @@ -469,7 +473,7 @@ impl PendingChecks { Err(UtxoLookupError::UnknownChain) => { Err(LightningError { err: format!("Channel announced on an unknown chain ({})", - msg.chain_hash.encode().to_hex()), + msg.chain_hash.to_bytes().as_hex()), action: ErrorAction::IgnoreError }) }, @@ -559,7 +563,6 @@ mod tests { use super::*; use crate::routing::gossip::tests::*; use crate::util::test_utils::{TestChainSource, TestLogger}; - use crate::ln::msgs; use bitcoin::secp256k1::{Secp256k1, SecretKey}; @@ -574,7 +577,7 @@ mod tests { } fn get_test_objects() -> (msgs::ChannelAnnouncement, TestChainSource, - NetworkGraph>, bitcoin::Script, msgs::NodeAnnouncement, + NetworkGraph>, bitcoin::ScriptBuf, msgs::NodeAnnouncement, msgs::NodeAnnouncement, msgs::ChannelUpdate, msgs::ChannelUpdate, msgs::ChannelUpdate) { let secp_ctx = Secp256k1::new(); @@ -657,7 +660,7 @@ mod tests { assert!(network_graph.read_only().channels().get(&valid_announcement.contents.short_channel_id).is_none()); future.resolve_without_forwarding(&network_graph, - Ok(TxOut { value: 1_000_000, script_pubkey: bitcoin::Script::new() })); + Ok(TxOut { value: 1_000_000, script_pubkey: bitcoin::ScriptBuf::new() })); assert!(network_graph.read_only().channels().get(&valid_announcement.contents.short_channel_id).is_none()); } @@ -745,10 +748,11 @@ mod tests { Ok(TxOut { value: 1_000_000, script_pubkey: good_script })); assert_eq!(chan_update_a.contents.timestamp, chan_update_b.contents.timestamp); - assert!(network_graph.read_only().channels() + let graph_lock = network_graph.read_only(); + assert!(graph_lock.channels() .get(&valid_announcement.contents.short_channel_id).as_ref().unwrap() .one_to_two.as_ref().unwrap().last_update != - network_graph.read_only().channels() + graph_lock.channels() .get(&valid_announcement.contents.short_channel_id).as_ref().unwrap() .two_to_one.as_ref().unwrap().last_update); }