//! 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`].
/// 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 {
/// 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<TxOut, UtxoLookupError>);
+pub(crate) struct UtxoResolver(Result<TxOut, UtxoLookupError>);
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())
}
}
// 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 => {
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
});
}
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
})
},
}
fn get_test_objects() -> (msgs::ChannelAnnouncement, TestChainSource,
- NetworkGraph<Box<TestLogger>>, bitcoin::Script, msgs::NodeAnnouncement,
+ NetworkGraph<Box<TestLogger>>, bitcoin::ScriptBuf, msgs::NodeAnnouncement,
msgs::NodeAnnouncement, msgs::ChannelUpdate, msgs::ChannelUpdate, msgs::ChannelUpdate)
{
let secp_ctx = Secp256k1::new();
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());
}
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);
}