+ // If we receive announcement for the same channel (with UTXO lookups disabled),
+ // drop new one on the floor, since we can't see any changes.
+ match router.handle_channel_announcement(&valid_announcement) {
+ Ok(_) => panic!(),
+ Err(e) => assert_eq!(e.err, "Already have knowledge of channel")
+ };
+
+
+ // Test if an associated transaction were not on-chain (or not confirmed).
+ *chain_monitor.utxo_ret.lock().unwrap() = Err(chaininterface::ChainError::UnknownTx);
+ unsigned_announcement.short_channel_id += 1;
+
+ msghash = hash_to_message!(&Sha256dHash::hash(&unsigned_announcement.encode()[..])[..]);
+ let valid_announcement = ChannelAnnouncement {
+ node_signature_1: secp_ctx.sign(&msghash, node_1_privkey),
+ node_signature_2: secp_ctx.sign(&msghash, node_2_privkey),
+ bitcoin_signature_1: secp_ctx.sign(&msghash, node_1_btckey),
+ bitcoin_signature_2: secp_ctx.sign(&msghash, node_2_btckey),
+ contents: unsigned_announcement.clone(),
+ };
+
+ match router.handle_channel_announcement(&valid_announcement) {
+ Ok(_) => panic!(),
+ Err(e) => assert_eq!(e.err, "Channel announced without corresponding UTXO entry")
+ };
+
+
+ // Now test if the transaction is found in the UTXO set and the script is correct.
+ unsigned_announcement.short_channel_id += 1;
+ *chain_monitor.utxo_ret.lock().unwrap() = Ok((good_script.clone(), 0));
+ let channel_key = NetworkMap::get_key(unsigned_announcement.short_channel_id,
+ unsigned_announcement.chain_hash);
+
+ msghash = hash_to_message!(&Sha256dHash::hash(&unsigned_announcement.encode()[..])[..]);
+ let valid_announcement = ChannelAnnouncement {
+ node_signature_1: secp_ctx.sign(&msghash, node_1_privkey),
+ node_signature_2: secp_ctx.sign(&msghash, node_2_privkey),
+ bitcoin_signature_1: secp_ctx.sign(&msghash, node_1_btckey),
+ bitcoin_signature_2: secp_ctx.sign(&msghash, node_2_btckey),
+ contents: unsigned_announcement.clone(),
+ };
+ match router.handle_channel_announcement(&valid_announcement) {
+ Ok(res) => assert!(res),
+ _ => panic!()
+ };
+ {
+ let network = router.network_map.write().unwrap();
+ match network.channels.get(&channel_key) {
+ None => panic!(),
+ Some(_) => ()
+ }
+ }
+
+ // If we receive announcement for the same channel (but TX is not confirmed),
+ // drop new one on the floor, since we can't see any changes.
+ *chain_monitor.utxo_ret.lock().unwrap() = Err(chaininterface::ChainError::UnknownTx);
+ match router.handle_channel_announcement(&valid_announcement) {
+ Ok(_) => panic!(),
+ Err(e) => assert_eq!(e.err, "Channel announced without corresponding UTXO entry")
+ };
+
+ // But if it is confirmed, replace the channel
+ *chain_monitor.utxo_ret.lock().unwrap() = Ok((good_script, 0));
+ unsigned_announcement.features = ChannelFeatures::empty();
+ msghash = hash_to_message!(&Sha256dHash::hash(&unsigned_announcement.encode()[..])[..]);
+ let valid_announcement = ChannelAnnouncement {
+ node_signature_1: secp_ctx.sign(&msghash, node_1_privkey),
+ node_signature_2: secp_ctx.sign(&msghash, node_2_privkey),
+ bitcoin_signature_1: secp_ctx.sign(&msghash, node_1_btckey),
+ bitcoin_signature_2: secp_ctx.sign(&msghash, node_2_btckey),
+ contents: unsigned_announcement.clone(),
+ };
+ match router.handle_channel_announcement(&valid_announcement) {
+ Ok(res) => assert!(res),
+ _ => panic!()
+ };
+ {
+ let mut network = router.network_map.write().unwrap();
+ match network.channels.entry(channel_key) {
+ BtreeEntry::Occupied(channel_entry) => {
+ assert_eq!(channel_entry.get().features, ChannelFeatures::empty());
+ },
+ _ => panic!()
+ }
+ }
+
+ // Don't relay valid channels with excess data
+ unsigned_announcement.short_channel_id += 1;
+ unsigned_announcement.excess_data.push(1);
+ msghash = hash_to_message!(&Sha256dHash::hash(&unsigned_announcement.encode()[..])[..]);
+ let valid_announcement = ChannelAnnouncement {
+ node_signature_1: secp_ctx.sign(&msghash, node_1_privkey),
+ node_signature_2: secp_ctx.sign(&msghash, node_2_privkey),
+ bitcoin_signature_1: secp_ctx.sign(&msghash, node_1_btckey),
+ bitcoin_signature_2: secp_ctx.sign(&msghash, node_2_btckey),
+ contents: unsigned_announcement.clone(),
+ };
+ match router.handle_channel_announcement(&valid_announcement) {
+ Ok(res) => assert!(!res),
+ _ => panic!()
+ };
+
+ unsigned_announcement.excess_data = Vec::new();
+ let invalid_sig_announcement = ChannelAnnouncement {
+ node_signature_1: secp_ctx.sign(&msghash, node_1_privkey),
+ node_signature_2: secp_ctx.sign(&msghash, node_2_privkey),
+ bitcoin_signature_1: secp_ctx.sign(&msghash, node_1_btckey),
+ bitcoin_signature_2: secp_ctx.sign(&msghash, node_1_btckey),
+ contents: unsigned_announcement.clone(),
+ };
+ match router.handle_channel_announcement(&invalid_sig_announcement) {
+ Ok(_) => panic!(),
+ Err(e) => assert_eq!(e.err, "Invalid signature from remote node")
+ };
+
+ unsigned_announcement.node_id_1 = PublicKey::from_secret_key(&secp_ctx, node_2_privkey);
+ msghash = hash_to_message!(&Sha256dHash::hash(&unsigned_announcement.encode()[..])[..]);
+ let channel_to_itself_announcement = ChannelAnnouncement {
+ node_signature_1: secp_ctx.sign(&msghash, node_1_privkey),
+ node_signature_2: secp_ctx.sign(&msghash, node_1_privkey),
+ bitcoin_signature_1: secp_ctx.sign(&msghash, node_1_btckey),
+ bitcoin_signature_2: secp_ctx.sign(&msghash, node_2_btckey),
+ contents: unsigned_announcement.clone(),
+ };
+ match router.handle_channel_announcement(&channel_to_itself_announcement) {
+ Ok(_) => panic!(),
+ Err(e) => assert_eq!(e.err, "Channel announcement node had a channel with itself")
+ };
+ }
+
+ #[test]
+ fn handling_channel_update() {
+ let (secp_ctx, _, router) = create_router();
+ let node_1_privkey = &SecretKey::from_slice(&[42; 32]).unwrap();
+ let node_2_privkey = &SecretKey::from_slice(&[41; 32]).unwrap();
+ let node_id_1 = PublicKey::from_secret_key(&secp_ctx, node_1_privkey);
+ let node_id_2 = PublicKey::from_secret_key(&secp_ctx, node_2_privkey);
+ let node_1_btckey = &SecretKey::from_slice(&[40; 32]).unwrap();
+ let node_2_btckey = &SecretKey::from_slice(&[39; 32]).unwrap();
+
+ let zero_hash = Sha256dHash::hash(&[0; 32]);
+ let short_channel_id = 0;
+ let chain_hash = genesis_block(Network::Testnet).header.bitcoin_hash();
+ let channel_key = NetworkMap::get_key(short_channel_id, chain_hash);
+
+
+ {
+ // Announce a channel we will update
+ let unsigned_announcement = UnsignedChannelAnnouncement {
+ features: ChannelFeatures::empty(),
+ chain_hash,
+ short_channel_id,
+ node_id_1,
+ node_id_2,
+ bitcoin_key_1: PublicKey::from_secret_key(&secp_ctx, node_1_btckey),
+ bitcoin_key_2: PublicKey::from_secret_key(&secp_ctx, node_2_btckey),
+ excess_data: Vec::new(),
+ };
+
+ let msghash = hash_to_message!(&Sha256dHash::hash(&unsigned_announcement.encode()[..])[..]);
+ let valid_channel_announcement = ChannelAnnouncement {
+ node_signature_1: secp_ctx.sign(&msghash, node_1_privkey),
+ node_signature_2: secp_ctx.sign(&msghash, node_2_privkey),
+ bitcoin_signature_1: secp_ctx.sign(&msghash, node_1_btckey),
+ bitcoin_signature_2: secp_ctx.sign(&msghash, node_2_btckey),
+ contents: unsigned_announcement.clone(),
+ };
+ match router.handle_channel_announcement(&valid_channel_announcement) {
+ Ok(_) => (),
+ Err(_) => panic!()
+ };
+
+ }
+
+ let mut unsigned_channel_update = UnsignedChannelUpdate {
+ chain_hash,
+ short_channel_id,
+ timestamp: 100,
+ flags: 0,
+ cltv_expiry_delta: 144,
+ htlc_minimum_msat: 1000000,
+ fee_base_msat: 10000,
+ fee_proportional_millionths: 20,
+ excess_data: Vec::new()
+ };
+ let msghash = hash_to_message!(&Sha256dHash::hash(&unsigned_channel_update.encode()[..])[..]);
+ let valid_channel_update = ChannelUpdate {
+ signature: secp_ctx.sign(&msghash, node_1_privkey),
+ contents: unsigned_channel_update.clone()
+ };
+
+ match router.handle_channel_update(&valid_channel_update) {
+ Ok(res) => assert!(res),
+ _ => panic!()
+ };
+
+ {
+ let network = router.network_map.write().unwrap();
+ match network.channels.get(&channel_key) {
+ None => panic!(),
+ Some(channel_info) => {
+ assert_eq!(channel_info.one_to_two.cltv_expiry_delta, 144);
+ assert_eq!(channel_info.two_to_one.cltv_expiry_delta, u16::max_value());
+ }
+ }
+ }
+
+ unsigned_channel_update.timestamp += 100;
+ unsigned_channel_update.excess_data.push(1);
+ let msghash = hash_to_message!(&Sha256dHash::hash(&unsigned_channel_update.encode()[..])[..]);
+ let valid_channel_update = ChannelUpdate {
+ signature: secp_ctx.sign(&msghash, node_1_privkey),
+ contents: unsigned_channel_update.clone()
+ };
+ // Return false because contains excess data
+ match router.handle_channel_update(&valid_channel_update) {
+ Ok(res) => assert!(!res),
+ _ => panic!()
+ };
+
+ unsigned_channel_update.short_channel_id += 1;
+ let msghash = hash_to_message!(&Sha256dHash::hash(&unsigned_channel_update.encode()[..])[..]);
+ let valid_channel_update = ChannelUpdate {
+ signature: secp_ctx.sign(&msghash, node_1_privkey),
+ contents: unsigned_channel_update.clone()
+ };
+
+ match router.handle_channel_update(&valid_channel_update) {
+ Ok(_) => panic!(),
+ Err(e) => assert_eq!(e.err, "Couldn't find channel for update")
+ };
+ unsigned_channel_update.short_channel_id = short_channel_id;
+
+
+ // Even though previous update was not relayed further, we still accepted it,
+ // so we now won't accept update before the previous one.
+ unsigned_channel_update.timestamp -= 10;
+ let msghash = hash_to_message!(&Sha256dHash::hash(&unsigned_channel_update.encode()[..])[..]);
+ let valid_channel_update = ChannelUpdate {
+ signature: secp_ctx.sign(&msghash, node_1_privkey),
+ contents: unsigned_channel_update.clone()
+ };
+
+ match router.handle_channel_update(&valid_channel_update) {
+ Ok(_) => panic!(),
+ Err(e) => assert_eq!(e.err, "Update older than last processed update")
+ };
+ unsigned_channel_update.timestamp += 500;
+
+ let fake_msghash = hash_to_message!(&zero_hash);
+ let invalid_sig_channel_update = ChannelUpdate {
+ signature: secp_ctx.sign(&fake_msghash, node_1_privkey),
+ contents: unsigned_channel_update.clone()
+ };
+
+ match router.handle_channel_update(&invalid_sig_channel_update) {
+ Ok(_) => panic!(),
+ Err(e) => assert_eq!(e.err, "Invalid signature from remote node")
+ };
+
+ }
+
+ #[test]
+ fn handling_htlc_fail_channel_update() {
+ let (secp_ctx, our_id, router) = create_router();
+ let node_1_privkey = &SecretKey::from_slice(&[42; 32]).unwrap();
+ let node_2_privkey = &SecretKey::from_slice(&[41; 32]).unwrap();
+ let node_id_1 = PublicKey::from_secret_key(&secp_ctx, node_1_privkey);
+ let node_id_2 = PublicKey::from_secret_key(&secp_ctx, node_2_privkey);
+ let node_1_btckey = &SecretKey::from_slice(&[40; 32]).unwrap();
+ let node_2_btckey = &SecretKey::from_slice(&[39; 32]).unwrap();
+
+ let short_channel_id = 0;
+ let chain_hash = genesis_block(Network::Testnet).header.bitcoin_hash();
+ let channel_key = NetworkMap::get_key(short_channel_id, chain_hash);
+
+ {
+ // There is only local node in the table at the beginning.