Skip to content

Commit 9d7b961

Browse files
author
Antoine Riard
committed
Implement check channel_announcement is on ChainWatchInterface chain
Add ChainWatchInterface in Router Add test on channel_announcement + test utilities Fix typo
1 parent a1aaea5 commit 9d7b961

File tree

7 files changed

+127
-13
lines changed

7 files changed

+127
-13
lines changed

fuzz/fuzz_targets/full_stack_target.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -232,12 +232,12 @@ pub fn do_test(data: &[u8], logger: &Arc<Logger>) {
232232
Err(_) => return,
233233
};
234234

235-
let watch = Arc::new(ChainWatchInterfaceUtil::new(Arc::clone(&logger)));
235+
let watch = Arc::new(ChainWatchInterfaceUtil::new(Network::Bitcoin, Arc::clone(&logger)));
236236
let broadcast = Arc::new(TestBroadcaster{});
237237
let monitor = channelmonitor::SimpleManyChannelMonitor::new(watch.clone(), broadcast.clone());
238238

239239
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();
240-
let router = Arc::new(Router::new(PublicKey::from_secret_key(&secp_ctx, &our_network_key), Arc::clone(&logger)));
240+
let router = Arc::new(Router::new(PublicKey::from_secret_key(&secp_ctx, &our_network_key), watch.clone(), Arc::clone(&logger)));
241241

242242
let peers = RefCell::new([false; 256]);
243243
let mut loss_detector = MoneyLossDetector::new(&peers, channelmanager.clone(), monitor.clone(), PeerManager::new(MessageHandler {

fuzz/fuzz_targets/router_target.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ extern crate bitcoin;
22
extern crate lightning;
33
extern crate secp256k1;
44

5+
use bitcoin::network::constants::Network;
6+
7+
use lightning::chain::chaininterface;
58
use lightning::ln::channelmanager::ChannelDetails;
69
use lightning::ln::msgs;
710
use lightning::ln::msgs::{MsgDecodable, RoutingMessageHandler};
@@ -107,9 +110,10 @@ pub fn do_test(data: &[u8]) {
107110
}
108111

109112
let logger: Arc<Logger> = Arc::new(test_logger::TestLogger{});
113+
let chain_monitor = Arc::new(chaininterface::ChainWatchInterfaceUtil::new(Network::Bitcoin, Arc::clone(&logger)));
110114

111115
let our_pubkey = get_pubkey!();
112-
let router = Router::new(our_pubkey.clone(), Arc::clone(&logger));
116+
let router = Router::new(our_pubkey.clone(), chain_monitor, Arc::clone(&logger));
113117

114118
loop {
115119
match get_slice!(1)[0] {

src/chain/chaininterface.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use bitcoin::blockdata::block::{Block, BlockHeader};
22
use bitcoin::blockdata::transaction::Transaction;
33
use bitcoin::blockdata::script::Script;
44
use bitcoin::util::hash::Sha256dHash;
5+
use bitcoin::network::constants::Network;
56
use util::logger::Logger;
67
use std::sync::{Mutex,Weak,MutexGuard,Arc};
78
use std::sync::atomic::{AtomicUsize, Ordering};
@@ -24,6 +25,9 @@ pub trait ChainWatchInterface: Sync + Send {
2425

2526
fn register_listener(&self, listener: Weak<ChainListener>);
2627
//TODO: unregister
28+
29+
/// Gets the chain currently watched
30+
fn get_network(&self) -> Network;
2731
}
2832

2933
/// An interface to send a transaction to the Bitcoin network.
@@ -69,6 +73,7 @@ pub trait FeeEstimator: Sync + Send {
6973
/// Utility to capture some common parts of ChainWatchInterface implementors.
7074
/// Keeping a local copy of this in a ChainWatchInterface implementor is likely useful.
7175
pub struct ChainWatchInterfaceUtil {
76+
network: Network,
7277
watched: Mutex<(Vec<Script>, Vec<(Sha256dHash, u32)>, bool)>, //TODO: Something clever to optimize this
7378
listeners: Mutex<Vec<Weak<ChainListener>>>,
7479
reentered: AtomicUsize,
@@ -99,11 +104,16 @@ impl ChainWatchInterface for ChainWatchInterfaceUtil {
99104
let mut vec = self.listeners.lock().unwrap();
100105
vec.push(listener);
101106
}
107+
108+
fn get_network(&self) -> Network {
109+
self.network
110+
}
102111
}
103112

104113
impl ChainWatchInterfaceUtil {
105-
pub fn new(logger: Arc<Logger>) -> ChainWatchInterfaceUtil {
114+
pub fn new(network: Network, logger: Arc<Logger>) -> ChainWatchInterfaceUtil {
106115
ChainWatchInterfaceUtil {
116+
network: network,
107117
watched: Mutex::new((Vec::new(), Vec::new(), false)),
108118
listeners: Mutex::new(Vec::new()),
109119
reentered: AtomicUsize::new(1),

src/chain/transaction.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ pub struct OutPoint {
1313
}
1414

1515
impl OutPoint {
16-
/// Creates a new `OutPoint` from the txid an the index.
16+
/// Creates a new `OutPoint` from the txid and the index.
1717
pub fn new(txid: Sha256dHash, index: u16) -> OutPoint {
1818
OutPoint { txid, index }
1919
}

src/ln/channel.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2002,6 +2002,12 @@ impl Channel {
20022002
self.channel_value_satoshis
20032003
}
20042004

2005+
//TODO: Testing purpose only, should be changed in another way after #81
2006+
#[cfg(test)]
2007+
pub fn get_local_keys(&self) -> &ChannelKeys {
2008+
&self.local_keys
2009+
}
2010+
20052011
/// Allowed in any state (including after shutdown)
20062012
pub fn get_channel_update_count(&self) -> u32 {
20072013
self.channel_update_count

src/ln/channelmanager.rs

Lines changed: 87 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2093,13 +2093,14 @@ mod tests {
20932093
use bitcoin::util::hash::Sha256dHash;
20942094
use bitcoin::blockdata::block::{Block, BlockHeader};
20952095
use bitcoin::blockdata::transaction::{Transaction, TxOut};
2096+
use bitcoin::blockdata::constants::genesis_block;
20962097
use bitcoin::network::constants::Network;
20972098
use bitcoin::network::serialize::serialize;
20982099
use bitcoin::network::serialize::BitcoinHash;
20992100

21002101
use hex;
21012102

2102-
use secp256k1::Secp256k1;
2103+
use secp256k1::{Secp256k1, Message};
21032104
use secp256k1::key::{PublicKey,SecretKey};
21042105

21052106
use crypto::sha2::Sha256;
@@ -2817,7 +2818,7 @@ mod tests {
28172818

28182819
for _ in 0..node_count {
28192820
let feeest = Arc::new(test_utils::TestFeeEstimator { sat_per_kw: 253 });
2820-
let chain_monitor = Arc::new(chaininterface::ChainWatchInterfaceUtil::new(Arc::clone(&logger)));
2821+
let chain_monitor = Arc::new(chaininterface::ChainWatchInterfaceUtil::new(Network::Testnet, Arc::clone(&logger)));
28212822
let tx_broadcaster = Arc::new(test_utils::TestBroadcaster{txn_broadcasted: Mutex::new(Vec::new())});
28222823
let chan_monitor = Arc::new(test_utils::TestChannelMonitor::new(chain_monitor.clone(), tx_broadcaster.clone()));
28232824
let node_id = {
@@ -2826,7 +2827,7 @@ mod tests {
28262827
SecretKey::from_slice(&secp_ctx, &key_slice).unwrap()
28272828
};
28282829
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();
2829-
let router = Router::new(PublicKey::from_secret_key(&secp_ctx, &node_id), Arc::clone(&logger));
2830+
let router = Router::new(PublicKey::from_secret_key(&secp_ctx, &node_id), chain_monitor.clone(), Arc::clone(&logger));
28302831
nodes.push(Node { feeest, chain_monitor, tx_broadcaster, chan_monitor, node, router });
28312832
}
28322833

@@ -3236,4 +3237,87 @@ mod tests {
32363237
assert_eq!(channel_state.by_id.len(), 0);
32373238
assert_eq!(channel_state.short_to_id.len(), 0);
32383239
}
3240+
3241+
#[test]
3242+
fn test_invalid_channel_announcement() {
3243+
//Test BOLT 7 channel_announcement msg requirement for final node, gather data to build customed channel_announcement msgs
3244+
let secp_ctx = Secp256k1::new();
3245+
let nodes = create_network(2);
3246+
3247+
let chan_announcement = create_chan_between_nodes(&nodes[0], &nodes[1]);
3248+
3249+
let a_channel_lock = nodes[0].node.channel_state.lock().unwrap();
3250+
let b_channel_lock = nodes[1].node.channel_state.lock().unwrap();
3251+
let as_chan = a_channel_lock.by_id.get(&chan_announcement.3).unwrap();
3252+
let bs_chan = b_channel_lock.by_id.get(&chan_announcement.3).unwrap();
3253+
3254+
let _ = nodes[0].router.handle_htlc_fail_channel_update(&msgs::HTLCFailChannelUpdate::ChannelClosed { short_channel_id : as_chan.get_short_channel_id().unwrap() } );
3255+
3256+
let as_bitcoin_key = PublicKey::from_secret_key(&secp_ctx, &as_chan.get_local_keys().funding_key);
3257+
let bs_bitcoin_key = PublicKey::from_secret_key(&secp_ctx, &bs_chan.get_local_keys().funding_key);
3258+
3259+
let as_network_key = nodes[0].node.get_our_node_id();
3260+
let bs_network_key = nodes[1].node.get_our_node_id();
3261+
3262+
let were_node_one = as_bitcoin_key.serialize()[..] < bs_bitcoin_key.serialize()[..];
3263+
3264+
let mut unsigned_msg;
3265+
let mut chan_announcement;
3266+
3267+
macro_rules! dummy_unsigned_msg {
3268+
() => {
3269+
unsigned_msg = msgs::UnsignedChannelAnnouncement {
3270+
features: msgs::GlobalFeatures::new(),
3271+
chain_hash: genesis_block(Network::Testnet).header.bitcoin_hash(),
3272+
short_channel_id: as_chan.get_short_channel_id().unwrap(),
3273+
node_id_1: if were_node_one { as_network_key } else { bs_network_key },
3274+
node_id_2: if !were_node_one { bs_network_key } else { as_network_key },
3275+
bitcoin_key_1: if were_node_one { as_bitcoin_key } else { bs_bitcoin_key },
3276+
bitcoin_key_2: if !were_node_one { bs_bitcoin_key } else { as_bitcoin_key },
3277+
excess_data: Vec::new(),
3278+
};
3279+
}
3280+
}
3281+
3282+
macro_rules! sign_msg {
3283+
() => {
3284+
let msghash = Message::from_slice(&Sha256dHash::from_data(&unsigned_msg.encode()[..])[..]).unwrap();
3285+
let as_bitcoin_sig = secp_ctx.sign(&msghash, &as_chan.get_local_keys().funding_key);
3286+
let bs_bitcoin_sig = secp_ctx.sign(&msghash, &bs_chan.get_local_keys().funding_key);
3287+
let as_node_sig = secp_ctx.sign(&msghash, &nodes[0].node.our_network_key);
3288+
let bs_node_sig = secp_ctx.sign(&msghash, &nodes[1].node.our_network_key);
3289+
chan_announcement = msgs::ChannelAnnouncement {
3290+
node_signature_1 : if were_node_one { as_node_sig } else { bs_node_sig},
3291+
node_signature_2 : if !were_node_one { bs_node_sig } else { as_node_sig},
3292+
bitcoin_signature_1: if were_node_one { as_bitcoin_sig } else { bs_bitcoin_sig },
3293+
bitcoin_signature_2 : if !were_node_one { bs_bitcoin_sig } else { as_bitcoin_sig },
3294+
contents: unsigned_msg
3295+
}
3296+
}
3297+
}
3298+
3299+
//TODO: test short_channel_id correspond to a P2WSH and that output isn't spent
3300+
3301+
dummy_unsigned_msg!();
3302+
sign_msg!();
3303+
assert_eq!(nodes[0].router.handle_channel_announcement(&chan_announcement).unwrap(), true);
3304+
let _ = nodes[0].router.handle_htlc_fail_channel_update(&msgs::HTLCFailChannelUpdate::ChannelClosed { short_channel_id : as_chan.get_short_channel_id().unwrap() } );
3305+
3306+
// Configured with Network::Testnet
3307+
dummy_unsigned_msg!();
3308+
unsigned_msg.chain_hash = genesis_block(Network::Bitcoin).header.bitcoin_hash();
3309+
sign_msg!();
3310+
match nodes[0].router.handle_channel_announcement(&chan_announcement) {
3311+
Ok(_) => assert!(false),
3312+
Err(_) => assert!(true),
3313+
}
3314+
3315+
dummy_unsigned_msg!();
3316+
unsigned_msg.chain_hash = Sha256dHash::from_data(&[1,2,3,4,5,6,7,8,9]);
3317+
sign_msg!();
3318+
match nodes[0].router.handle_channel_announcement(&chan_announcement) {
3319+
Ok(_) => assert!(false),
3320+
Err(_) => assert!(true),
3321+
}
3322+
}
32393323
}

src/ln/router.rs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@ use secp256k1::{Secp256k1,Message};
33
use secp256k1;
44

55
use bitcoin::util::hash::Sha256dHash;
6+
use bitcoin::blockdata::constants::genesis_block;
7+
use bitcoin::network::serialize::BitcoinHash;
68

9+
use chain::chaininterface::ChainWatchInterface;
710
use ln::channelmanager;
811
use ln::msgs::{ErrorAction,HandleError,RoutingMessageHandler,MsgEncodable,NetAddress,GlobalFeatures};
912
use ln::msgs;
@@ -155,6 +158,7 @@ pub struct RouteHint {
155158
pub struct Router {
156159
secp_ctx: Secp256k1<secp256k1::VerifyOnly>,
157160
network_map: RwLock<NetworkMap>,
161+
chain_monitor: Arc<ChainWatchInterface>,
158162
logger: Arc<Logger>,
159163
}
160164

@@ -201,13 +205,15 @@ impl RoutingMessageHandler for Router {
201205
secp_verify_sig!(self.secp_ctx, &msg_hash, &msg.bitcoin_signature_1, &msg.contents.bitcoin_key_1);
202206
secp_verify_sig!(self.secp_ctx, &msg_hash, &msg.bitcoin_signature_2, &msg.contents.bitcoin_key_2);
203207

204-
//TODO: Call blockchain thing to ask if the short_channel_id is valid
205-
//TODO: Only allow bitcoin chain_hash
206-
207208
if msg.contents.features.requires_unknown_bits() {
208209
panic!("Unknown-required-features ChannelAnnouncements should never deserialize!");
209210
}
210211

212+
//TODO: Call blockchain thing to ask if the short_channel_id is valid
213+
if msg.contents.chain_hash != genesis_block(self.chain_monitor.get_network()).header.bitcoin_hash() {
214+
return Err(HandleError{err: "Channel announced on an unknown chain", action: Some(ErrorAction::IgnoreError)});
215+
}
216+
211217
let mut network = self.network_map.write().unwrap();
212218

213219
match network.channels.entry(NetworkMap::get_key(msg.contents.short_channel_id, msg.contents.chain_hash)) {
@@ -388,7 +394,7 @@ struct DummyDirectionalChannelInfo {
388394
}
389395

390396
impl Router {
391-
pub fn new(our_pubkey: PublicKey, logger: Arc<Logger>) -> Router {
397+
pub fn new(our_pubkey: PublicKey, chain_monitor: Arc<ChainWatchInterface>, logger: Arc<Logger>) -> Router {
392398
let mut nodes = HashMap::new();
393399
nodes.insert(our_pubkey.clone(), NodeInfo {
394400
channels: Vec::new(),
@@ -407,6 +413,7 @@ impl Router {
407413
our_node_id: our_pubkey,
408414
nodes: nodes,
409415
}),
416+
chain_monitor,
410417
logger,
411418
}
412419
}
@@ -632,13 +639,15 @@ impl Router {
632639

633640
#[cfg(test)]
634641
mod tests {
642+
use chain::chaininterface;
635643
use ln::channelmanager;
636644
use ln::router::{Router,NodeInfo,NetworkMap,ChannelInfo,DirectionalChannelInfo,RouteHint};
637645
use ln::msgs::GlobalFeatures;
638646
use util::test_utils;
639647
use util::logger::Logger;
640648

641649
use bitcoin::util::hash::Sha256dHash;
650+
use bitcoin::network::constants::Network;
642651

643652
use hex;
644653

@@ -652,7 +661,8 @@ mod tests {
652661
let secp_ctx = Secp256k1::new();
653662
let our_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex::decode("0101010101010101010101010101010101010101010101010101010101010101").unwrap()[..]).unwrap());
654663
let logger: Arc<Logger> = Arc::new(test_utils::TestLogger::new());
655-
let router = Router::new(our_id, Arc::clone(&logger));
664+
let chain_monitor = Arc::new(chaininterface::ChainWatchInterfaceUtil::new(Network::Testnet, Arc::clone(&logger)));
665+
let router = Router::new(our_id, chain_monitor, Arc::clone(&logger));
656666

657667
// Build network from our_id to node8:
658668
//

0 commit comments

Comments
 (0)