]> git.bitcoin.ninja Git - rust-lightning/blob - lightning/src/routing/utxo.rs
828ea3764fb454f4ed8ef0d50719130ba941cb5c
[rust-lightning] / lightning / src / routing / utxo.rs
1 // This file is Copyright its original authors, visible in version control
2 // history.
3 //
4 // This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
5 // or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
7 // You may not use this file except in accordance with one or both of these
8 // licenses.
9
10 //! This module contains traits for LDK to access UTXOs to check gossip data is correct.
11 //!
12 //! When lightning nodes gossip channel information, they resist DoS attacks by checking that each
13 //! channel matches a UTXO on-chain, requiring at least some marginal on-chain transacting in
14 //! order to announce a channel. This module handles that checking.
15
16 use bitcoin::{BlockHash, TxOut};
17 use bitcoin::hashes::hex::ToHex;
18
19 use crate::ln::chan_utils::make_funding_redeemscript_from_slices;
20 use crate::ln::msgs::{self, LightningError, ErrorAction};
21 use crate::util::ser::Writeable;
22
23 use crate::prelude::*;
24
25 use core::ops::Deref;
26
27 /// An error when accessing the chain via [`UtxoLookup`].
28 #[derive(Clone, Debug)]
29 pub enum UtxoLookupError {
30         /// The requested chain is unknown.
31         UnknownChain,
32
33         /// The requested transaction doesn't exist or hasn't confirmed.
34         UnknownTx,
35 }
36
37 /// The `UtxoLookup` trait defines behavior for accessing on-chain UTXOs.
38 pub trait UtxoLookup {
39         /// Returns the transaction output of a funding transaction encoded by [`short_channel_id`].
40         /// Returns an error if `genesis_hash` is for a different chain or if such a transaction output
41         /// is unknown.
42         ///
43         /// [`short_channel_id`]: https://github.com/lightning/bolts/blob/master/07-routing-gossip.md#definition-of-short_channel_id
44         fn get_utxo(&self, genesis_hash: &BlockHash, short_channel_id: u64) -> Result<TxOut, UtxoLookupError>;
45 }
46
47 pub(crate) fn check_channel_announcement<U: Deref>(
48         utxo_lookup: &Option<U>, msg: &msgs::UnsignedChannelAnnouncement
49 ) -> Result<Option<u64>, msgs::LightningError> where U::Target: UtxoLookup {
50         let utxo_value = match utxo_lookup {
51                 &None => {
52                         // Tentatively accept, potentially exposing us to DoS attacks
53                         None
54                 },
55                 &Some(ref utxo_lookup) => {
56                         match utxo_lookup.get_utxo(&msg.chain_hash, msg.short_channel_id) {
57                                 Ok(TxOut { value, script_pubkey }) => {
58                                         let expected_script =
59                                                 make_funding_redeemscript_from_slices(msg.bitcoin_key_1.as_slice(), msg.bitcoin_key_2.as_slice()).to_v0_p2wsh();
60                                         if script_pubkey != expected_script {
61                                                 return Err(LightningError{err: format!("Channel announcement key ({}) didn't match on-chain script ({})", expected_script.to_hex(), script_pubkey.to_hex()), action: ErrorAction::IgnoreError});
62                                         }
63                                         //TODO: Check if value is worth storing, use it to inform routing, and compare it
64                                         //to the new HTLC max field in channel_update
65                                         Some(value)
66                                 },
67                                 Err(UtxoLookupError::UnknownChain) => {
68                                         return Err(LightningError{err: format!("Channel announced on an unknown chain ({})", msg.chain_hash.encode().to_hex()), action: ErrorAction::IgnoreError});
69                                 },
70                                 Err(UtxoLookupError::UnknownTx) => {
71                                         return Err(LightningError{err: "Channel announced without corresponding UTXO entry".to_owned(), action: ErrorAction::IgnoreError});
72                                 },
73                         }
74                 }
75         };
76         Ok(utxo_value)
77 }