Implement get_network, get_chain_txo, get_spendable_outpoint in
authorAntoine Riard <ariard@student.42.fr>
Thu, 30 Aug 2018 01:40:18 +0000 (01:40 +0000)
committerAntoine Riard <ariard@student.42.fr>
Thu, 30 Aug 2018 01:40:18 +0000 (01:40 +0000)
ChainWatchInterface to Router check on channel_announcement

Needed for BOLT 7

src/chain/chaininterface.rs
src/ln/router.rs

index bda99b2d83c2d47ecf95a274b9cdc412f47db705..533b007fe5e0945fe271a18ec294e2845c6c4895 100644 (file)
@@ -1,11 +1,26 @@
 use bitcoin::blockdata::block::{Block, BlockHeader};
 use bitcoin::blockdata::transaction::Transaction;
 use bitcoin::blockdata::script::Script;
+use bitcoin::blockdata::constants::genesis_block;
 use bitcoin::util::hash::Sha256dHash;
+use bitcoin::network::constants::Network;
+use bitcoin::network::serialize::BitcoinHash;
 use util::logger::Logger;
 use std::sync::{Mutex,Weak,MutexGuard,Arc};
 use std::sync::atomic::{AtomicUsize, Ordering};
 
+/// Used to give chain error details upstream
+pub enum ChainError {
+       /// Chain isn't supported
+       NotSupported,
+       /// Chain isn't the one watched
+       NotWatched,
+       /// Tx isn't there
+       UnknownTx,
+       /// Tx isn't confirmed
+       UnconfirmedTx,
+}
+
 /// An interface to request notification of certain scripts as they appear the
 /// chain.
 /// Note that all of the functions implemented here *must* be reentrant-safe (obviously - they're
@@ -24,6 +39,15 @@ pub trait ChainWatchInterface: Sync + Send {
 
        fn register_listener(&self, listener: Weak<ChainListener>);
        //TODO: unregister
+
+       /// Gets the chain currently watched
+       fn get_network(&self) -> Network;
+
+       /// Gets the script and value in satoshis for a given txid and outpoint index
+       fn get_chain_txo(&self, genesis_hash: Sha256dHash, txid: Sha256dHash, output_index: u16) -> Result<(Script, u64), ChainError>;
+
+       /// Gets if outpoint is among UTXO
+       fn get_spendable_outpoint(&self, genesis_hash: Sha256dHash, txid: Sha256dHash, output_index: u16) -> Result<bool, ChainError>;
 }
 
 /// An interface to send a transaction to the Bitcoin network.
@@ -69,12 +93,21 @@ pub trait FeeEstimator: Sync + Send {
 /// Utility to capture some common parts of ChainWatchInterface implementors.
 /// Keeping a local copy of this in a ChainWatchInterface implementor is likely useful.
 pub struct ChainWatchInterfaceUtil {
+       network: Network,
        watched: Mutex<(Vec<Script>, Vec<(Sha256dHash, u32)>, bool)>, //TODO: Something clever to optimize this
        listeners: Mutex<Vec<Weak<ChainListener>>>,
        reentered: AtomicUsize,
        logger: Arc<Logger>,
 }
 
+macro_rules! watched_chain {
+       ($self: ident, $hash: expr) => {
+               if $hash != genesis_block($self.get_network()).header.bitcoin_hash() {
+                       return Err(ChainError::NotWatched);
+               }
+       }
+}
+
 /// Register listener
 impl ChainWatchInterface for ChainWatchInterfaceUtil {
        fn install_watch_script(&self, script_pub_key: &Script) {
@@ -99,11 +132,31 @@ impl ChainWatchInterface for ChainWatchInterfaceUtil {
                let mut vec = self.listeners.lock().unwrap();
                vec.push(listener);
        }
+
+       fn get_network(&self) -> Network {
+               self.network
+       }
+
+
+       fn get_chain_txo(&self, genesis_hash: Sha256dHash, _txid: Sha256dHash, _output_index: u16) -> Result<(Script, u64), ChainError> {
+               watched_chain!(self, genesis_hash);
+
+               //TODO: self.BlockchainStore.get_txo(txid, output_index)
+               Err(ChainError::UnknownTx)
+       }
+
+       fn get_spendable_outpoint(&self, genesis_hash: Sha256dHash, _txid: Sha256dHash, _output_index: u16) -> Result<bool, ChainError> {
+               watched_chain!(self, genesis_hash);
+
+               //TODO: self.BlockchainStore.is_utxo(txid, output_index)
+               Err(ChainError::UnknownTx)
+       }
 }
 
 impl ChainWatchInterfaceUtil {
-       pub fn new(logger: Arc<Logger>) -> ChainWatchInterfaceUtil {
+       pub fn new(network: Network, logger: Arc<Logger>) -> ChainWatchInterfaceUtil {
                ChainWatchInterfaceUtil {
+                       network: network,
                        watched: Mutex::new((Vec::new(), Vec::new(), false)),
                        listeners: Mutex::new(Vec::new()),
                        reentered: AtomicUsize::new(1),
index e329b7e696c4b08aec2889797064f6f2a757725f..620008b4bc284ee4110e02cd2488a108974b3e6f 100644 (file)
@@ -3,6 +3,8 @@ use secp256k1::{Secp256k1,Message};
 use secp256k1;
 
 use bitcoin::util::hash::Sha256dHash;
+use bitcoin::blockdata::constants::genesis_block;
+use bitcoin::network::serialize::BitcoinHash;
 
 use chain::chaininterface::ChainWatchInterface;
 use ln::channelmanager;
@@ -203,13 +205,15 @@ impl RoutingMessageHandler for Router {
                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() {
                        panic!("Unknown-required-features ChannelAnnouncements should never deserialize!");
                }
 
+               //TODO: Call blockchain thing to ask if the short_channel_id is valid
+               if msg.contents.chain_hash != genesis_block(self.chain_monitor.get_network()).header.bitcoin_hash() {
+                       return Err(HandleError{err: "Channel announced on an unknown chain", action: Some(ErrorAction::IgnoreError)});
+               }
+
                let mut network = self.network_map.write().unwrap();
 
                match network.channels.entry(NetworkMap::get_key(msg.contents.short_channel_id, msg.contents.chain_hash)) {
@@ -643,6 +647,7 @@ mod tests {
        use util::logger::Logger;
 
        use bitcoin::util::hash::Sha256dHash;
+       use bitcoin::network::constants::Network;
 
        use hex;