Skip to content

Commit 0d27b72

Browse files
author
Antoine Riard
committed
Implement check channel_announcement is on Bitcoin Mainnet or Testnet
Add test on valid channel_announcement + test utilities Fix typo
1 parent 3c1ef64 commit 0d27b72

File tree

5 files changed

+114
-5
lines changed

5 files changed

+114
-5
lines changed

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: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2000,6 +2000,16 @@ impl Channel {
20002000
self.channel_value_satoshis
20012001
}
20022002

2003+
#[cfg(test)]
2004+
pub fn get_local_keys(&self) -> &ChannelKeys {
2005+
&self.local_keys
2006+
}
2007+
2008+
#[cfg(test)]
2009+
pub fn get_secp_ctx(&self) -> &Secp256k1<secp256k1::All> {
2010+
&self.secp_ctx
2011+
}
2012+
20032013
/// Allowed in any state (including after shutdown)
20042014
pub fn get_channel_update_count(&self) -> u32 {
20052015
self.channel_update_count

src/ln/channelmanager.rs

Lines changed: 88 additions & 1 deletion
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;
@@ -3239,4 +3240,90 @@ 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 nodes = create_network(2);
3248+
3249+
let chan_announcement = create_chan_between_nodes(&nodes[0], &nodes[1]);
3250+
3251+
let a_channel_lock = nodes[0].node.channel_state.lock().unwrap();
3252+
let b_channel_lock = nodes[1].node.channel_state.lock().unwrap();
3253+
let as_chan = a_channel_lock.by_id.get(&chan_announcement.3).unwrap();
3254+
let bs_chan = b_channel_lock.by_id.get(&chan_announcement.3).unwrap();
3255+
3256+
let _ = nodes[0].router.remove_channel_info(as_chan.get_short_channel_id().unwrap(), genesis_block(Network::Testnet).header.bitcoin_hash());
3257+
3258+
let as_bitcoin_key = PublicKey::from_secret_key(&as_chan.get_secp_ctx(), &as_chan.get_local_keys().funding_key);
3259+
let bs_bitcoin_key = PublicKey::from_secret_key(&bs_chan.get_secp_ctx(), &bs_chan.get_local_keys().funding_key);
3260+
3261+
let as_network_key = nodes[0].node.get_our_node_id();
3262+
let bs_network_key = nodes[1].node.get_our_node_id();
3263+
3264+
let were_node_one = as_bitcoin_key.serialize()[..] < bs_bitcoin_key.serialize()[..];
3265+
3266+
let mut unsigned_msg;
3267+
let mut chan_announcement;
3268+
3269+
macro_rules! dummy_unsigned_msg {
3270+
() => {
3271+
unsigned_msg = msgs::UnsignedChannelAnnouncement {
3272+
features: msgs::GlobalFeatures::new(),
3273+
chain_hash: genesis_block(Network::Testnet).header.bitcoin_hash(),
3274+
short_channel_id: as_chan.get_short_channel_id().unwrap(),
3275+
node_id_1: if were_node_one { as_network_key } else { bs_network_key },
3276+
node_id_2: if !were_node_one { bs_network_key } else { as_network_key },
3277+
bitcoin_key_1: if were_node_one { as_bitcoin_key } else { bs_bitcoin_key },
3278+
bitcoin_key_2: if !were_node_one { bs_bitcoin_key } else { as_bitcoin_key },
3279+
};
3280+
}
3281+
}
3282+
3283+
macro_rules! sign_msg {
3284+
() => {
3285+
let msghash = Message::from_slice(&Sha256dHash::from_data(&unsigned_msg.encode()[..])[..]).unwrap();
3286+
let as_bitcoin_sig = as_chan.get_secp_ctx().sign(&msghash, &as_chan.get_local_keys().funding_key);
3287+
let bs_bitcoin_sig = bs_chan.get_secp_ctx().sign(&msghash, &bs_chan.get_local_keys().funding_key);
3288+
let as_node_sig = as_chan.get_secp_ctx().sign(&msghash, &nodes[0].node.our_network_key);
3289+
let bs_node_sig = bs_chan.get_secp_ctx().sign(&msghash, &nodes[1].node.our_network_key);
3290+
chan_announcement = msgs::ChannelAnnouncement {
3291+
node_signature_1 : if were_node_one { as_node_sig } else { bs_node_sig},
3292+
node_signature_2 : if !were_node_one { bs_node_sig } else { as_node_sig},
3293+
bitcoin_signature_1: if were_node_one { as_bitcoin_sig } else { bs_bitcoin_sig },
3294+
bitcoin_signature_2 : if !were_node_one { bs_bitcoin_sig } else { as_bitcoin_sig },
3295+
contents: unsigned_msg
3296+
}
3297+
}
3298+
}
3299+
3300+
dummy_unsigned_msg!();
3301+
unsigned_msg.features = msgs::GlobalFeatures::dummy_new(vec!(0xff, 0xff, 0xff, 0xff));
3302+
sign_msg!();
3303+
match nodes[0].router.handle_channel_announcement(&chan_announcement) {
3304+
Ok(_) => assert!(false),
3305+
Err(_) => assert!(true),
3306+
}
3307+
3308+
//TODO: test short_channel_id correspond to a P2WSH and that output isn't spent
3309+
3310+
dummy_unsigned_msg!();
3311+
sign_msg!();
3312+
assert_eq!(nodes[0].router.handle_channel_announcement(&chan_announcement).unwrap(), true);
3313+
let _ = nodes[0].router.remove_channel_info(as_chan.get_short_channel_id().unwrap(), genesis_block(Network::Testnet).header.bitcoin_hash());
3314+
3315+
dummy_unsigned_msg!();
3316+
unsigned_msg.chain_hash = genesis_block(Network::Bitcoin).header.bitcoin_hash();
3317+
sign_msg!();
3318+
assert_eq!(nodes[0].router.handle_channel_announcement(&chan_announcement).unwrap(), true);
3319+
let _ = nodes[0].router.remove_channel_info(as_chan.get_short_channel_id().unwrap(), genesis_block(Network::Bitcoin).header.bitcoin_hash());
3320+
3321+
dummy_unsigned_msg!();
3322+
unsigned_msg.chain_hash = Sha256dHash::from_data(&[1,2,3,4,5,6,7,8,9]);
3323+
sign_msg!();
3324+
match nodes[0].router.handle_channel_announcement(&chan_announcement) {
3325+
Ok(_) => assert!(false),
3326+
Err(_) => assert!(true),
3327+
}
3328+
}
32423329
}

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 dummy_new(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: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ 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::constants::Network;
8+
use bitcoin::network::serialize::BitcoinHash;
69

710
use ln::channelmanager;
811
use ln::msgs::{ErrorAction,HandleError,RoutingMessageHandler,MsgEncodable,NetAddress,GlobalFeatures};
@@ -197,13 +200,15 @@ impl RoutingMessageHandler for Router {
197200
secp_verify_sig!(self.secp_ctx, &msg_hash, &msg.bitcoin_signature_1, &msg.contents.bitcoin_key_1);
198201
secp_verify_sig!(self.secp_ctx, &msg_hash, &msg.bitcoin_signature_2, &msg.contents.bitcoin_key_2);
199202

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

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

209214
match network.channels.entry(NetworkMap::get_key(msg.contents.short_channel_id, msg.contents.chain_hash)) {

0 commit comments

Comments
 (0)