Skip to content

Commit 103d62d

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 7659877 commit 103d62d

File tree

6 files changed

+134
-10
lines changed

6 files changed

+134
-10
lines changed

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
@@ -2000,6 +2000,12 @@ impl Channel {
20002000
self.channel_value_satoshis
20012001
}
20022002

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

src/ln/channelmanager.rs

Lines changed: 94 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2096,13 +2096,14 @@ mod tests {
20962096
use bitcoin::util::hash::Sha256dHash;
20972097
use bitcoin::blockdata::block::{Block, BlockHeader};
20982098
use bitcoin::blockdata::transaction::{Transaction, TxOut};
2099+
use bitcoin::blockdata::constants::genesis_block;
20992100
use bitcoin::network::constants::Network;
21002101
use bitcoin::network::serialize::serialize;
21012102
use bitcoin::network::serialize::BitcoinHash;
21022103

21032104
use hex;
21042105

2105-
use secp256k1::Secp256k1;
2106+
use secp256k1::{Secp256k1, Message};
21062107
use secp256k1::key::{PublicKey,SecretKey};
21072108

21082109
use crypto::sha2::Sha256;
@@ -2820,7 +2821,7 @@ mod tests {
28202821

28212822
for _ in 0..node_count {
28222823
let feeest = Arc::new(test_utils::TestFeeEstimator { sat_per_kw: 253 });
2823-
let chain_monitor = Arc::new(chaininterface::ChainWatchInterfaceUtil::new(Arc::clone(&logger)));
2824+
let chain_monitor = Arc::new(chaininterface::ChainWatchInterfaceUtil::new(Network::Testnet, Arc::clone(&logger)));
28242825
let tx_broadcaster = Arc::new(test_utils::TestBroadcaster{txn_broadcasted: Mutex::new(Vec::new())});
28252826
let chan_monitor = Arc::new(test_utils::TestChannelMonitor::new(chain_monitor.clone(), tx_broadcaster.clone()));
28262827
let node_id = {
@@ -2829,7 +2830,7 @@ mod tests {
28292830
SecretKey::from_slice(&secp_ctx, &key_slice).unwrap()
28302831
};
28312832
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();
2832-
let router = Router::new(PublicKey::from_secret_key(&secp_ctx, &node_id), Arc::clone(&logger));
2833+
let router = Router::new(PublicKey::from_secret_key(&secp_ctx, &node_id), chain_monitor.clone(), Arc::clone(&logger));
28332834
nodes.push(Node { feeest, chain_monitor, tx_broadcaster, chan_monitor, node, router });
28342835
}
28352836

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

src/ln/msgs.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,13 @@ impl GlobalFeatures {
120120
}
121121
}
122122

123+
#[cfg(test)]
124+
pub fn new_with_flags(v: Vec<u8>) -> GlobalFeatures {
125+
GlobalFeatures {
126+
flags: v,
127+
}
128+
}
129+
123130
pub fn requires_unknown_bits(&self) -> bool {
124131
for &byte in self.flags.iter() {
125132
if (byte & 0x55) != 0 {

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

@@ -197,13 +201,15 @@ impl RoutingMessageHandler for Router {
197201
secp_verify_sig!(self.secp_ctx, &msg_hash, &msg.bitcoin_signature_1, &msg.contents.bitcoin_key_1);
198202
secp_verify_sig!(self.secp_ctx, &msg_hash, &msg.bitcoin_signature_2, &msg.contents.bitcoin_key_2);
199203

200-
//TODO: Call blockchain thing to ask if the short_channel_id is valid
201-
//TODO: Only allow bitcoin chain_hash
202-
203204
if msg.contents.features.requires_unknown_bits() {
204205
return Err(HandleError{err: "Channel announcement required unknown feature flags", action: None});
205206
}
206207

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

209215
match network.channels.entry(NetworkMap::get_key(msg.contents.short_channel_id, msg.contents.chain_hash)) {
@@ -384,7 +390,7 @@ struct DummyDirectionalChannelInfo {
384390
}
385391

386392
impl Router {
387-
pub fn new(our_pubkey: PublicKey, logger: Arc<Logger>) -> Router {
393+
pub fn new(our_pubkey: PublicKey, chain_monitor: Arc<ChainWatchInterface>, logger: Arc<Logger>) -> Router {
388394
let mut nodes = HashMap::new();
389395
nodes.insert(our_pubkey.clone(), NodeInfo {
390396
channels: Vec::new(),
@@ -403,6 +409,7 @@ impl Router {
403409
our_node_id: our_pubkey,
404410
nodes: nodes,
405411
}),
412+
chain_monitor,
406413
logger,
407414
}
408415
}
@@ -628,13 +635,15 @@ impl Router {
628635

629636
#[cfg(test)]
630637
mod tests {
638+
use chain::chaininterface;
631639
use ln::channelmanager;
632640
use ln::router::{Router,NodeInfo,NetworkMap,ChannelInfo,DirectionalChannelInfo,RouteHint};
633641
use ln::msgs::GlobalFeatures;
634642
use util::test_utils;
635643
use util::logger::Logger;
636644

637645
use bitcoin::util::hash::Sha256dHash;
646+
use bitcoin::network::constants::Network;
638647

639648
use hex;
640649

@@ -648,7 +657,8 @@ mod tests {
648657
let secp_ctx = Secp256k1::new();
649658
let our_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex::decode("0101010101010101010101010101010101010101010101010101010101010101").unwrap()[..]).unwrap());
650659
let logger: Arc<Logger> = Arc::new(test_utils::TestLogger::new());
651-
let router = Router::new(our_id, Arc::clone(&logger));
660+
let chain_monitor = Arc::new(chaininterface::ChainWatchInterfaceUtil::new(Network::Testnet, Arc::clone(&logger)));
661+
let router = Router::new(our_id, chain_monitor, Arc::clone(&logger));
652662

653663
// Build network from our_id to node8:
654664
//

0 commit comments

Comments
 (0)