use bitcoin::network::constants::Network;
use bitcoin::network::serialize::BitcoinHash;
use bitcoin::util::hash::Sha256dHash;
-use bitcoin::util::uint::Uint256;
use secp256k1::key::{SecretKey,PublicKey};
use secp256k1::{Secp256k1,Message};
const MIN_HTLC_RELAY_HOLDING_CELL_MILLIS: u32 = 50;
struct ChannelHolder {
- by_id: HashMap<Uint256, Channel>,
- short_to_id: HashMap<u64, Uint256>,
+ by_id: HashMap<[u8; 32], Channel>,
+ short_to_id: HashMap<u64, [u8; 32]>,
next_forward: Instant,
/// short channel id -> forward infos. Key of 0 means payments received
forward_htlcs: HashMap<u64, Vec<PendingForwardHTLCInfo>>,
claimable_htlcs: HashMap<[u8; 32], PendingOutboundHTLC>,
}
struct MutChannelHolder<'a> {
- by_id: &'a mut HashMap<Uint256, Channel>,
- short_to_id: &'a mut HashMap<u64, Uint256>,
+ by_id: &'a mut HashMap<[u8; 32], Channel>,
+ short_to_id: &'a mut HashMap<u64, [u8; 32]>,
next_forward: &'a mut Instant,
/// short channel id -> forward infos. Key of 0 means payments received
forward_htlcs: &'a mut HashMap<u64, Vec<PendingForwardHTLCInfo>>,
/// thereafter this is the txid of the funding transaction xor the funding transaction output).
/// Note that this means this value is *not* persistent - it can change once during the
/// lifetime of the channel.
- pub channel_id: Uint256,
+ pub channel_id: [u8; 32],
/// The position of the funding transaction in the chain. None if the funding transaction has
/// not yet been confirmed and the channel fully opened.
pub short_channel_id: Option<u64>,
/// Begins the process of closing a channel. After this call (plus some timeout), no new HTLCs
/// will be accepted on the given channel, and after additional timeout/the closing of all
/// pending HTLCs, the channel will be closed on chain.
- pub fn close_channel(&self, channel_id: &Uint256) -> Result<msgs::Shutdown, HandleError> {
- let (res, chan_option) = {
+ /// May generate a SendShutdown event on success, which should be relayed.
+ pub fn close_channel(&self, channel_id: &[u8; 32]) -> Result<(), HandleError> {
+ let (res, node_id, chan_option) = {
let mut channel_state_lock = self.channel_state.lock().unwrap();
let channel_state = channel_state_lock.borrow_parts();
match channel_state.by_id.entry(channel_id.clone()) {
if let Some(short_id) = chan_entry.get().get_short_channel_id() {
channel_state.short_to_id.remove(&short_id);
}
- (res, Some(chan_entry.remove_entry().1))
- } else { (res, None) }
+ (res, chan_entry.get().get_their_node_id(), Some(chan_entry.remove_entry().1))
+ } else { (res, chan_entry.get().get_their_node_id(), None) }
},
hash_map::Entry::Vacant(_) => return Err(HandleError{err: "No such channel", action: None})
}
// unknown_next_peer...I dunno who that is anymore....
self.fail_htlc_backwards_internal(self.channel_state.lock().unwrap(), &payment_hash, HTLCFailReason::Reason { failure_code: 0x4000 | 10, data: Vec::new() });
}
- if let Some(chan) = chan_option {
+ let chan_update = if let Some(chan) = chan_option {
if let Ok(update) = self.get_channel_update(&chan) {
- let mut events = self.pending_events.lock().unwrap();
- events.push(events::Event::BroadcastChannelUpdate {
- msg: update
- });
- }
+ Some(update)
+ } else { None }
+ } else { None };
+
+ let mut events = self.pending_events.lock().unwrap();
+ if let Some(update) = chan_update {
+ events.push(events::Event::BroadcastChannelUpdate {
+ msg: update
+ });
}
- Ok(res.0)
+ events.push(events::Event::SendShutdown {
+ node_id,
+ msg: res.0
+ });
+
+ Ok(())
}
#[inline]
/// Call this upon creation of a funding transaction for the given channel.
/// Panics if a funding transaction has already been provided for this channel.
- pub fn funding_transaction_generated(&self, temporary_channel_id: &Uint256, funding_txo: OutPoint) {
+ pub fn funding_transaction_generated(&self, temporary_channel_id: &[u8; 32], funding_txo: OutPoint) {
let (chan, msg, chan_monitor) = {
let mut channel_state = self.channel_state.lock().unwrap();
- match channel_state.by_id.remove(&temporary_channel_id) {
+ match channel_state.by_id.remove(temporary_channel_id) {
Some(mut chan) => {
match chan.get_outbound_funding_created(funding_txo) {
Ok(funding_msg) => {
}
fn get_announcement_sigs(&self, chan: &Channel) -> Result<Option<msgs::AnnouncementSignatures>, HandleError> {
- if !chan.is_usable() { return Ok(None) }
+ if !chan.is_usable() || !chan.should_announce() { return Ok(None) }
let (announcement, our_bitcoin_sig) = chan.get_channel_announcement(self.get_our_node_id(), self.genesis_hash.clone())?;
let msghash = Message::from_slice(&Sha256dHash::from_data(&announcement.encode()[..])[..]).unwrap();
use bitcoin::util::misc::hex_bytes;
use bitcoin::util::hash::Sha256dHash;
- use bitcoin::util::uint::Uint256;
- use bitcoin::blockdata::block::BlockHeader;
+ use bitcoin::blockdata::block::{Block, BlockHeader};
use bitcoin::blockdata::transaction::{Transaction, TxOut};
use bitcoin::network::constants::Network;
use bitcoin::network::serialize::serialize;
}
fn confirm_transaction(chain: &chaininterface::ChainWatchInterfaceUtil, tx: &Transaction, chan_id: u32) {
+ assert!(chain.does_match_tx(tx));
let mut header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
chain.block_connected_checked(&header, 1, &[tx; 1], &[chan_id; 1]);
for i in 2..100 {
}
static mut CHAN_COUNT: u32 = 0;
- fn create_chan_between_nodes(node_a: &Node, node_b: &Node) -> (msgs::ChannelAnnouncement, msgs::ChannelUpdate, msgs::ChannelUpdate, Uint256, Transaction) {
+ fn create_chan_between_nodes(node_a: &Node, node_b: &Node) -> (msgs::ChannelAnnouncement, msgs::ChannelUpdate, msgs::ChannelUpdate, [u8; 32], Transaction) {
node_a.node.create_channel(node_b.node.get_our_node_id(), 100000, 42).unwrap();
let events_1 = node_a.node.get_and_clear_pending_events();
((*announcement).clone(), (*as_update).clone(), (*bs_update).clone(), channel_id, tx)
}
- fn create_announced_chan_between_nodes(nodes: &Vec<Node>, a: usize, b: usize) -> (msgs::ChannelUpdate, msgs::ChannelUpdate, Uint256, Transaction) {
+ fn create_announced_chan_between_nodes(nodes: &Vec<Node>, a: usize, b: usize) -> (msgs::ChannelUpdate, msgs::ChannelUpdate, [u8; 32], Transaction) {
let chan_announcement = create_chan_between_nodes(&nodes[a], &nodes[b]);
for node in nodes {
assert!(node.router.handle_channel_announcement(&chan_announcement.0).unwrap());
(chan_announcement.1, chan_announcement.2, chan_announcement.3, chan_announcement.4)
}
- fn close_channel(outbound_node: &Node, inbound_node: &Node, channel_id: &Uint256, funding_tx: Transaction, close_inbound_first: bool) -> (msgs::ChannelUpdate, msgs::ChannelUpdate) {
+ fn close_channel(outbound_node: &Node, inbound_node: &Node, channel_id: &[u8; 32], funding_tx: Transaction, close_inbound_first: bool) -> (msgs::ChannelUpdate, msgs::ChannelUpdate) {
let (node_a, broadcaster_a) = if close_inbound_first { (&inbound_node.node, &inbound_node.tx_broadcaster) } else { (&outbound_node.node, &outbound_node.tx_broadcaster) };
let (node_b, broadcaster_b) = if close_inbound_first { (&outbound_node.node, &outbound_node.tx_broadcaster) } else { (&inbound_node.node, &inbound_node.tx_broadcaster) };
let (tx_a, tx_b);
- let shutdown_a = node_a.close_channel(channel_id).unwrap();
+ node_a.close_channel(channel_id).unwrap();
+ let events_1 = node_a.get_and_clear_pending_events();
+ assert_eq!(events_1.len(), 1);
+ let shutdown_a = match events_1[0] {
+ Event::SendShutdown { ref node_id, ref msg } => {
+ assert_eq!(node_id, &node_b.get_our_node_id());
+ msg.clone()
+ },
+ _ => panic!("Unexpected event"),
+ };
+
let (shutdown_b, mut closing_signed_b) = node_b.handle_shutdown(&node_a.get_our_node_id(), &shutdown_a).unwrap();
if !close_inbound_first {
assert!(closing_signed_b.is_none());
funding_tx_map.insert(funding_tx.txid(), funding_tx);
tx_a.verify(&funding_tx_map).unwrap();
- let events_1 = node_a.get_and_clear_pending_events();
- assert_eq!(events_1.len(), 1);
- let as_update = match events_1[0] {
+ let events_2 = node_a.get_and_clear_pending_events();
+ assert_eq!(events_2.len(), 1);
+ let as_update = match events_2[0] {
Event::BroadcastChannelUpdate { ref msg } => {
msg.clone()
},
_ => panic!("Unexpected event"),
};
- let events_2 = node_b.get_and_clear_pending_events();
- assert_eq!(events_2.len(), 1);
- let bs_update = match events_2[0] {
+ let events_3 = node_b.get_and_clear_pending_events();
+ assert_eq!(events_3.len(), 1);
+ let bs_update = match events_3[0] {
Event::BroadcastChannelUpdate { ref msg } => {
msg.clone()
},
#[derive(PartialEq)]
enum HTLCType { NONE, TIMEOUT, SUCCESS }
- fn test_txn_broadcast(node: &Node, chan: &(msgs::ChannelUpdate, msgs::ChannelUpdate, Uint256, Transaction), commitment_tx: Option<Transaction>, has_htlc_tx: HTLCType) -> Vec<Transaction> {
+ fn test_txn_broadcast(node: &Node, chan: &(msgs::ChannelUpdate, msgs::ChannelUpdate, [u8; 32], Transaction), commitment_tx: Option<Transaction>, has_htlc_tx: HTLCType) -> Vec<Transaction> {
let mut node_txn = node.tx_broadcaster.txn_broadcasted.lock().unwrap();
assert!(node_txn.len() >= if commitment_tx.is_some() { 0 } else { 1 } + if has_htlc_tx == HTLCType::NONE { 0 } else { 1 });
// Simple case with no pending HTLCs:
nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), true);
{
- let node_txn = test_txn_broadcast(&nodes[1], &chan_1, None, HTLCType::NONE);
+ let mut node_txn = test_txn_broadcast(&nodes[1], &chan_1, None, HTLCType::NONE);
let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
- nodes[0].chain_monitor.block_connected_checked(&header, 1, &[&node_txn[0]; 1], &[4; 1]);
+ nodes[0].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![node_txn.drain(..).next().unwrap()] }, 1);
assert_eq!(nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().len(), 0);
}
get_announce_close_broadcast_events(&nodes, 0, 1);
// Simple case of one pending HTLC to HTLC-Timeout
nodes[1].node.peer_disconnected(&nodes[2].node.get_our_node_id(), true);
{
- let node_txn = test_txn_broadcast(&nodes[1], &chan_2, None, HTLCType::TIMEOUT);
+ let mut node_txn = test_txn_broadcast(&nodes[1], &chan_2, None, HTLCType::TIMEOUT);
let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
- nodes[2].chain_monitor.block_connected_checked(&header, 1, &[&node_txn[0]; 1], &[4; 1]);
+ nodes[2].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![node_txn.drain(..).next().unwrap()] }, 1);
assert_eq!(nodes[2].tx_broadcaster.txn_broadcasted.lock().unwrap().len(), 0);
}
get_announce_close_broadcast_events(&nodes, 1, 2);
claim_funds!(nodes[3], nodes[2], payment_preimage_1);
let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
- nodes[3].chain_monitor.block_connected_checked(&header, 1, &[&node_txn[0]; 1], &[4; 1]);
+ nodes[3].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![node_txn[0].clone()] }, 1);
check_preimage_claim(&nodes[3], &node_txn);
}
test_txn_broadcast(&nodes[4], &chan_4, None, HTLCType::SUCCESS);
header = BlockHeader { version: 0x20000000, prev_blockhash: header.bitcoin_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
- nodes[4].chain_monitor.block_connected_checked(&header, TEST_FINAL_CLTV - 5, &[&node_txn[0]; 1], &[4; 1]);
+ nodes[4].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![node_txn[0].clone()] }, TEST_FINAL_CLTV - 5);
check_preimage_claim(&nodes[4], &node_txn);
}
{
let mut header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
- nodes[1].chain_monitor.block_connected_checked(&header, 1, &vec![&revoked_local_txn[0]; 1], &[4; 1]);
+ nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1);
{
let mut node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap();
assert_eq!(node_txn.len(), 1);
node_txn.clear();
}
- nodes[0].chain_monitor.block_connected_checked(&header, 1, &vec![&revoked_local_txn[0]; 1], &[4; 0]);
+ nodes[0].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1);
let node_txn = test_txn_broadcast(&nodes[0], &chan_5, Some(revoked_local_txn[0].clone()), HTLCType::TIMEOUT);
header = BlockHeader { version: 0x20000000, prev_blockhash: header.bitcoin_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
- nodes[1].chain_monitor.block_connected_checked(&header, 1, &[&node_txn[1]; 1], &[4; 1]);
+ nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![node_txn[1].clone()] }, 1);
//TODO: At this point nodes[1] should claim the revoked HTLC-Timeout output, but that's
//not yet implemented in ChannelMonitor