From fa2d2bd6d9301df8c3c6ed4588fdc16177b5d109 Mon Sep 17 00:00:00 2001 From: Antoine Riard Date: Thu, 30 Aug 2018 01:37:37 +0000 Subject: [PATCH 1/5] Add ChainWatchInterface in Router --- fuzz/fuzz_targets/full_stack_target.rs | 4 ++-- fuzz/fuzz_targets/router_target.rs | 6 +++++- src/ln/channelmanager.rs | 6 +++--- src/ln/router.rs | 9 +++++++-- 4 files changed, 17 insertions(+), 8 deletions(-) diff --git a/fuzz/fuzz_targets/full_stack_target.rs b/fuzz/fuzz_targets/full_stack_target.rs index e5c12539ece..ced754acb51 100644 --- a/fuzz/fuzz_targets/full_stack_target.rs +++ b/fuzz/fuzz_targets/full_stack_target.rs @@ -232,12 +232,12 @@ pub fn do_test(data: &[u8], logger: &Arc) { Err(_) => return, }; - let watch = Arc::new(ChainWatchInterfaceUtil::new(Arc::clone(&logger))); + let watch = Arc::new(ChainWatchInterfaceUtil::new(Network::Bitcoin, Arc::clone(&logger))); let broadcast = Arc::new(TestBroadcaster{}); let monitor = channelmonitor::SimpleManyChannelMonitor::new(watch.clone(), broadcast.clone()); let channelmanager = ChannelManager::new(our_network_key, slice_to_be32(get_slice!(4)), get_slice!(1)[0] != 0, Network::Bitcoin, fee_est.clone(), monitor.clone(), watch.clone(), broadcast.clone(), Arc::clone(&logger)).unwrap(); - let router = Arc::new(Router::new(PublicKey::from_secret_key(&secp_ctx, &our_network_key), Arc::clone(&logger))); + let router = Arc::new(Router::new(PublicKey::from_secret_key(&secp_ctx, &our_network_key), watch.clone(), Arc::clone(&logger))); let peers = RefCell::new([false; 256]); let mut loss_detector = MoneyLossDetector::new(&peers, channelmanager.clone(), monitor.clone(), PeerManager::new(MessageHandler { diff --git a/fuzz/fuzz_targets/router_target.rs b/fuzz/fuzz_targets/router_target.rs index 469db990ffc..5d374f9538a 100644 --- a/fuzz/fuzz_targets/router_target.rs +++ b/fuzz/fuzz_targets/router_target.rs @@ -2,6 +2,9 @@ extern crate bitcoin; extern crate lightning; extern crate secp256k1; +use bitcoin::network::constants::Network; + +use lightning::chain::chaininterface; use lightning::ln::channelmanager::ChannelDetails; use lightning::ln::msgs; use lightning::ln::msgs::{MsgDecodable, RoutingMessageHandler}; @@ -107,9 +110,10 @@ pub fn do_test(data: &[u8]) { } let logger: Arc = Arc::new(test_logger::TestLogger{}); + let chain_monitor = Arc::new(chaininterface::ChainWatchInterfaceUtil::new(Network::Bitcoin, Arc::clone(&logger))); let our_pubkey = get_pubkey!(); - let router = Router::new(our_pubkey.clone(), Arc::clone(&logger)); + let router = Router::new(our_pubkey.clone(), chain_monitor, Arc::clone(&logger)); loop { match get_slice!(1)[0] { diff --git a/src/ln/channelmanager.rs b/src/ln/channelmanager.rs index 6a0e55a2c8a..60d8f0a658d 100644 --- a/src/ln/channelmanager.rs +++ b/src/ln/channelmanager.rs @@ -2816,7 +2816,7 @@ mod tests { for _ in 0..node_count { let feeest = Arc::new(test_utils::TestFeeEstimator { sat_per_kw: 253 }); - let chain_monitor = Arc::new(chaininterface::ChainWatchInterfaceUtil::new(Arc::clone(&logger))); + let chain_monitor = Arc::new(chaininterface::ChainWatchInterfaceUtil::new(Network::Testnet, Arc::clone(&logger))); let tx_broadcaster = Arc::new(test_utils::TestBroadcaster{txn_broadcasted: Mutex::new(Vec::new())}); let chan_monitor = Arc::new(test_utils::TestChannelMonitor::new(chain_monitor.clone(), tx_broadcaster.clone())); let node_id = { @@ -2825,8 +2825,8 @@ mod tests { SecretKey::from_slice(&secp_ctx, &key_slice).unwrap() }; let node = ChannelManager::new(node_id.clone(), 0, true, Network::Testnet, feeest.clone(), chan_monitor.clone(), chain_monitor.clone(), tx_broadcaster.clone(), Arc::clone(&logger)).unwrap(); - let router = Router::new(PublicKey::from_secret_key(&secp_ctx, &node_id), Arc::clone(&logger)); - nodes.push(Node { chain_monitor, tx_broadcaster, chan_monitor, node, router }); + let router = Router::new(PublicKey::from_secret_key(&secp_ctx, &node_id), chain_monitor.clone(), Arc::clone(&logger)); + nodes.push(Node { feeest, chain_monitor, tx_broadcaster, chan_monitor, node, router }); } nodes diff --git a/src/ln/router.rs b/src/ln/router.rs index a71eb913ce5..e329b7e696c 100644 --- a/src/ln/router.rs +++ b/src/ln/router.rs @@ -4,6 +4,7 @@ use secp256k1; use bitcoin::util::hash::Sha256dHash; +use chain::chaininterface::ChainWatchInterface; use ln::channelmanager; use ln::msgs::{ErrorAction,HandleError,RoutingMessageHandler,MsgEncodable,NetAddress,GlobalFeatures}; use ln::msgs; @@ -155,6 +156,7 @@ pub struct RouteHint { pub struct Router { secp_ctx: Secp256k1, network_map: RwLock, + chain_monitor: Arc, logger: Arc, } @@ -388,7 +390,7 @@ struct DummyDirectionalChannelInfo { } impl Router { - pub fn new(our_pubkey: PublicKey, logger: Arc) -> Router { + pub fn new(our_pubkey: PublicKey, chain_monitor: Arc, logger: Arc) -> Router { let mut nodes = HashMap::new(); nodes.insert(our_pubkey.clone(), NodeInfo { channels: Vec::new(), @@ -407,6 +409,7 @@ impl Router { our_node_id: our_pubkey, nodes: nodes, }), + chain_monitor, logger, } } @@ -632,6 +635,7 @@ impl Router { #[cfg(test)] mod tests { + use chain::chaininterface; use ln::channelmanager; use ln::router::{Router,NodeInfo,NetworkMap,ChannelInfo,DirectionalChannelInfo,RouteHint}; use ln::msgs::GlobalFeatures; @@ -652,7 +656,8 @@ mod tests { let secp_ctx = Secp256k1::new(); let our_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex::decode("0101010101010101010101010101010101010101010101010101010101010101").unwrap()[..]).unwrap()); let logger: Arc = Arc::new(test_utils::TestLogger::new()); - let router = Router::new(our_id, Arc::clone(&logger)); + let chain_monitor = Arc::new(chaininterface::ChainWatchInterfaceUtil::new(Network::Testnet, Arc::clone(&logger))); + let router = Router::new(our_id, chain_monitor, Arc::clone(&logger)); // Build network from our_id to node8: // From 6a12ff7e946b2e47deb971ece2b0eef41911394d Mon Sep 17 00:00:00 2001 From: Antoine Riard Date: Thu, 30 Aug 2018 01:40:18 +0000 Subject: [PATCH 2/5] Implement get_chain_utxo and ChainError in ChainWatchInterface to Router check on channel_announcement Needed for BOLT 7 --- src/chain/chaininterface.rs | 30 +++++++++++++++++++++++++++++- src/ln/router.rs | 21 +++++++++++++++++---- 2 files changed, 46 insertions(+), 5 deletions(-) diff --git a/src/chain/chaininterface.rs b/src/chain/chaininterface.rs index bda99b2d83c..78a40099c35 100644 --- a/src/chain/chaininterface.rs +++ b/src/chain/chaininterface.rs @@ -1,11 +1,24 @@ 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 { + /// Client doesn't support UTXO lookup (but the chain hash matches our genesis block hash) + NotSupported, + /// Chain isn't the one watched + NotWatched, + /// Tx doesn't exist or is unconfirmed + UnknownTx, +} + /// 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 +37,12 @@ pub trait ChainWatchInterface: Sync + Send { fn register_listener(&self, listener: Weak); //TODO: unregister + + /// Gets the script and value in satoshis for a given unspent transaction output given a + /// short_channel_id (aka unspent_tx_output_identier). For BTC/tBTC channels the top three + /// bytes are the block height, the next 3 the transaction index within the block, and the + /// final two the output within the transaction. + fn get_chain_utxo(&self, genesis_hash: Sha256dHash, unspent_tx_output_identifier: u64) -> Result<(Script, u64), ChainError>; } /// An interface to send a transaction to the Bitcoin network. @@ -69,6 +88,7 @@ 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