]> git.bitcoin.ninja Git - rust-lightning/commitdiff
initial checkin
authorMatt Corallo <git@bluematt.me>
Mon, 25 Dec 2017 06:05:27 +0000 (01:05 -0500)
committerMatt Corallo <git@bluematt.me>
Fri, 16 Feb 2018 23:09:48 +0000 (18:09 -0500)
26 files changed:
.gitignore [new file with mode: 0644]
Cargo.toml [new file with mode: 0644]
README.md [new file with mode: 0644]
src/chain/bitcoincorerpcchain.rs [new file with mode: 0644]
src/chain/chaininterface.rs [new file with mode: 0644]
src/chain/mod.rs [new file with mode: 0644]
src/chain/rustbitcoinchain.rs [new file with mode: 0644]
src/lib.rs [new file with mode: 0644]
src/ln/chan_utils.rs [new file with mode: 0644]
src/ln/channel.rs [new file with mode: 0644]
src/ln/channelmanager.rs [new file with mode: 0644]
src/ln/channelmonitor.rs [new file with mode: 0644]
src/ln/mod.rs [new file with mode: 0644]
src/ln/msgs.rs [new file with mode: 0644]
src/ln/peer_channel_encryptor.rs [new file with mode: 0644]
src/ln/peer_handler.rs [new file with mode: 0644]
src/ln/router.rs [new file with mode: 0644]
src/util/byte_utils.rs [new file with mode: 0644]
src/util/chacha20poly1305rfc.rs [new file with mode: 0644]
src/util/events.rs [new file with mode: 0644]
src/util/internal_traits.rs [new file with mode: 0644]
src/util/mod.rs [new file with mode: 0644]
src/util/test_utils.rs [new file with mode: 0644]
src/util/transaction_utils.rs [new file with mode: 0644]
src/wallet/mod.rs [new file with mode: 0644]
src/wallet/walletinterface.rs [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..c21e6c7
--- /dev/null
@@ -0,0 +1,5 @@
+/target/
+**/*.rs.bk
+Cargo.lock
+/target/
+**/*.rs.bk
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644 (file)
index 0000000..8290e28
--- /dev/null
@@ -0,0 +1,21 @@
+[package]
+name = "lightning"
+version = "0.0.1"
+authors = ["Matt Corallo"]
+license = "AGPL-3.0"
+repository = "https://github.com/TheBlueMatt/rust-lightning/"
+description = """
+A Bitcoin Lightning implementation in Rust.
+Still super-early code-dump quality and is missing large chunks. See README in git repo for suggested projects if you want to contribute. Don't have to bother telling you not to use this for anything serious, because you'd have to finish building it to even try.
+"""
+
+[features]
+# Supports tracking channels with a non-bitcoin chain hashes. Currently enables all kinds of fun DoS attacks.
+non_bitcoin_chain_hash_routing = []
+
+[dependencies]
+bitcoin = "0.10.7"
+rust-crypto = "0.2"
+rand = "0.3"
+secp256k1 = "0.8.1"
+num = "0.1"
diff --git a/README.md b/README.md
new file mode 100644 (file)
index 0000000..ac512ed
--- /dev/null
+++ b/README.md
@@ -0,0 +1,65 @@
+Rust-Lightning, not Rusty's Lightning!
+
+Currently somewhere near 5% towards usable, published to see if there is any
+real interest from folks in either contributing to or using a lightning rust
+library.
+
+The goal is to provide a full-featured but also incredibly flexible lightning
+implementation, allowing the user to decide how they wish to use it. With that
+in mind, everything should be exposed via simple, composable APIs. The user
+should be able to decide whether they wish to use their own threading/execution
+models, allowing usage inside of existing library architectures, or allow us to
+handle that for them. Same goes with network connections - if the user wishes
+to use their own networking stack, they should be able to do so! This all means
+that we should provide simple external interfaces which allow the user to drive
+all execution, while implementing sample execution drivers that create a
+full-featured lightning daemon by default.
+
+For security reasons, do not add new dependencies. Really do not add new
+non-optional/non-test/non-library dependencies. Really really do not add
+dependencies with dependencies. Do convince Andrew to cut down dependency usage
+in rust-bitcoin.
+
+Assorted random TODOs:
+
+ * Create a general timer interface - this should be passed around in reference
+   form to most objects to allow them to register functions which are called on
+   a timer. By default we should provide an implementation of this which uses
+   some newfangled rusty promise-y library, but should generally ensure a
+   client can simply integrate this into whatever existing timer interface
+   they use.
+
+ * Networking...having a simple bytes-in-bytes-out interface which does message
+   handling and calls our encryption layer is probably the right approach. We
+   should then also probably use the same promise-y library we use for timers
+   to do socket selection and reading/writing.
+
+ * Figure out how to expose when-to-connect and who-to-connect-to.
+
+ * Implement when-to-connect and who-to-connect-to based on route/node rumoring
+   and channelmanager state.
+
+ * Some kind of serialization format for on-disk storage of things like
+   channels, channelmonitors, routing db, etc.
+
+ * BOLT 10/network bootstrapping implementation.
+
+ * Some kind of DoS thing including ban tracking and putting that info in
+   HandleError (and also rename HandleError) to be propagated up...and then
+   handled.
+
+ * All the random TODOs and unimplemented!()s across the codebase.
+
+ * BOLT 11 (invoice/address creation/generation) implementation
+
+ * Type-ify our somewhat random usage of Uint256/[u8; 32]. Use Sha256dHash
+   where appropriate, create our own types for everything else.
+
+ * Some kind of logging subsystem/API.
+
+Notes on coding style:
+ * Use tabs. If you want to align lines, use spaces. Any desired alignment
+   should display fine at any tab-length display setting.
+
+License is AGPL, but with agreement that Matt can relicense under any other
+OSI-approved license at will (and likely will with sufficient motivation).
diff --git a/src/chain/bitcoincorerpcchain.rs b/src/chain/bitcoincorerpcchain.rs
new file mode 100644 (file)
index 0000000..f51b1d7
--- /dev/null
@@ -0,0 +1,41 @@
+use bitcoin::blockdata::transaction::Transaction;
+use bitcoin::blockdata::script::Script;
+use bitcoin::util::hash::Sha256dHash;
+
+use chain::chaininterface::{ChainWatchInterface,ChainWatchInterfaceUtil,ChainListener};
+
+use std::sync::Weak;
+
+pub struct BitcoinCoreRPCClientChain {
+       util: ChainWatchInterfaceUtil
+}
+
+impl ChainWatchInterface for BitcoinCoreRPCClientChain {
+       fn install_watch_script(&self, spk: Script) {
+               self.util.install_watch_script(spk)
+       }
+
+       fn install_watch_outpoint(&self, outpoint: (Sha256dHash, u32)) {
+               self.util.install_watch_outpoint(outpoint)
+       }
+
+       fn watch_all_txn(&self) {
+               self.util.watch_all_txn()
+       }
+
+       fn broadcast_transaction(&self, _tx: &Transaction) {
+               unimplemented!()
+       }
+
+       fn register_listener(&self, listener: Weak<ChainListener>) {
+               self.util.register_listener(listener)
+       }
+}
+
+impl BitcoinCoreRPCClientChain {
+       pub fn new() -> BitcoinCoreRPCClientChain {
+               BitcoinCoreRPCClientChain {
+                       util: ChainWatchInterfaceUtil::new(),
+               }
+       }
+}
diff --git a/src/chain/chaininterface.rs b/src/chain/chaininterface.rs
new file mode 100644 (file)
index 0000000..ef8f9bf
--- /dev/null
@@ -0,0 +1,130 @@
+use bitcoin::blockdata::block::BlockHeader;
+use bitcoin::blockdata::transaction::Transaction;
+use bitcoin::blockdata::script::Script;
+use bitcoin::util::hash::Sha256dHash;
+
+use std::sync::{Weak,Mutex};
+
+/// An interface to request notification of certain scripts as they appear the
+/// chain.
+pub trait ChainWatchInterface: Sync + Send {
+       /// Provides a scriptPubKey which much be watched for.
+       fn install_watch_script(&self, script_pub_key: Script);
+
+       /// Provides an outpoint which must be watched for, providing any transactions which spend the
+       /// given outpoint.
+       fn install_watch_outpoint(&self, outpoint: (Sha256dHash, u32));
+
+       /// Indicates that a listener needs to see all transactions.
+       fn watch_all_txn(&self);
+
+       /// Sends a transaction out to (hopefully) be mined
+       fn broadcast_transaction(&self, tx: &Transaction);
+
+       fn register_listener(&self, listener: Weak<ChainListener>);
+       //TODO: unregister
+}
+
+/// A trait indicating a desire to listen for events from the chain
+pub trait ChainListener: Sync + Send {
+       /// Notifies a listener that a block was connected.
+       /// Note that if a new script/transaction is watched during a block_connected call, the block
+       /// *must* be re-scanned with the new script/transaction and block_connected should be called
+       /// again with the same header and (at least) the new transactions.
+       /// This also means those counting confirmations using block_connected callbacks should watch
+       /// for duplicate headers and not count them towards confirmations!
+       fn block_connected(&self, header: &BlockHeader, height: u32, txn_matched: &[&Transaction], indexes_of_txn_matched: &[u32]);
+       /// Notifies a listener that a block was disconnected.
+       /// Unlike block_connected, this *must* never be called twice for the same disconnect event.
+       fn block_disconnected(&self, header: &BlockHeader);
+}
+
+pub enum ConfirmationTarget {
+       Background,
+       Normal,
+       HighPriority,
+}
+
+pub trait FeeEstimator: Sync + Send {
+       fn get_est_sat_per_vbyte(&self, ConfirmationTarget) -> u64;
+}
+
+/// Utility to capture some common parts of ChainWatchInterface implementors.
+/// Keeping a local copy of this in a ChainWatchInterface implementor is likely useful.
+pub struct ChainWatchInterfaceUtil {
+       watched: Mutex<(Vec<Script>, Vec<(Sha256dHash, u32)>, bool)>, //TODO: Something clever to optimize this
+       listeners: Mutex<Vec<Weak<ChainListener>>>,
+}
+
+impl ChainWatchInterfaceUtil {
+       pub fn new() -> ChainWatchInterfaceUtil {
+               ChainWatchInterfaceUtil {
+                       watched: Mutex::new((Vec::new(), Vec::new(), false)),
+                       listeners: Mutex::new(Vec::new()),
+               }
+       }
+
+       pub fn install_watch_script(&self, spk: Script) {
+               let mut watched = self.watched.lock().unwrap();
+               watched.0.push(Script::from(spk));
+       }
+
+       pub fn install_watch_outpoint(&self, outpoint: (Sha256dHash, u32)) {
+               let mut watched = self.watched.lock().unwrap();
+               watched.1.push(outpoint);
+       }
+
+       pub fn watch_all_txn(&self) { //TODO: refcnt this?
+               let mut watched = self.watched.lock().unwrap();
+               watched.2 = true;
+       }
+
+       pub fn register_listener(&self, listener: Weak<ChainListener>) {
+               let mut vec = self.listeners.lock().unwrap();
+               vec.push(listener);
+       }
+
+       pub fn do_call_block_connected(&self, header: &BlockHeader, height: u32, txn_matched: &[&Transaction], indexes_of_txn_matched: &[u32]) {
+               let listeners = self.listeners.lock().unwrap().clone();
+               for listener in listeners.iter() {
+                       match listener.upgrade() {
+                               Some(arc) => arc.block_connected(header, height, txn_matched, indexes_of_txn_matched),
+                               None => ()
+                       }
+               }
+       }
+
+       pub fn do_call_block_disconnected(&self, header: &BlockHeader) {
+               let listeners = self.listeners.lock().unwrap().clone();
+               for listener in listeners.iter() {
+                       match listener.upgrade() {
+                               Some(arc) => arc.block_disconnected(header),
+                               None => ()
+                       }
+               }
+       }
+
+       /// Checks if a given transaction matches the current filter
+       pub fn does_match_tx(&self, tx: &Transaction) -> bool {
+               let watched = self.watched.lock().unwrap();
+               if watched.2 {
+                       return true;
+               }
+               for out in tx.output.iter() {
+                       for script in watched.0.iter() {
+                               if script[..] == out.script_pubkey[..] {
+                                       return true;
+                               }
+                       }
+               }
+               for input in tx.input.iter() {
+                       for outpoint in watched.1.iter() {
+                               let &(outpoint_hash, outpoint_index) = outpoint;
+                               if outpoint_hash == input.prev_hash && outpoint_index == input.prev_index {
+                                       return true;
+                               }
+                       }
+               }
+               false
+       }
+}
diff --git a/src/chain/mod.rs b/src/chain/mod.rs
new file mode 100644 (file)
index 0000000..a2b1453
--- /dev/null
@@ -0,0 +1,3 @@
+pub mod chaininterface;
+pub mod bitcoincorerpcchain;
+pub mod rustbitcoinchain;
diff --git a/src/chain/rustbitcoinchain.rs b/src/chain/rustbitcoinchain.rs
new file mode 100644 (file)
index 0000000..13161e9
--- /dev/null
@@ -0,0 +1,66 @@
+use bitcoin::blockdata::blockchain::Blockchain;
+use bitcoin::blockdata::transaction::Transaction;
+use bitcoin::blockdata::block::Block;
+use bitcoin::blockdata::script::Script;
+use bitcoin::network::constants::Network;
+use bitcoin::util::hash::Sha256dHash;
+
+use chain::chaininterface::{ChainWatchInterface,ChainWatchInterfaceUtil,ChainListener};
+
+use std::sync::{Mutex,Weak};
+
+/// Implements a ChainWatchInterface using rust-bitcoin's Blockchain class
+pub struct ChainWatchImpl {
+       chain: Mutex<Blockchain>,
+       util: ChainWatchInterfaceUtil
+}
+
+unsafe impl Send for ChainWatchImpl {} //TODO: GAH WTF
+unsafe impl Sync for ChainWatchImpl {} //TODO: GAH WTF
+
+impl ChainWatchInterface for ChainWatchImpl {
+       fn install_watch_script(&self, spk: Script) {
+               self.util.install_watch_script(spk)
+       }
+
+       fn install_watch_outpoint(&self, outpoint: (Sha256dHash, u32)) {
+               self.util.install_watch_outpoint(outpoint)
+       }
+
+       fn watch_all_txn(&self) {
+               self.util.watch_all_txn()
+       }
+
+       fn broadcast_transaction(&self, _tx: &Transaction) {
+               unimplemented!()
+       }
+
+       fn register_listener(&self, listener: Weak<ChainListener>) {
+               self.util.register_listener(listener)
+       }
+}
+
+impl ChainWatchImpl {
+       pub fn new(network: Network) -> ChainWatchImpl {
+               ChainWatchImpl {
+                       chain: Mutex::new(Blockchain::new(network)),
+                       util: ChainWatchInterfaceUtil::new(),
+               }
+       }
+
+       pub fn add_block(&mut self, block: Block) {
+               {
+                       let mut txn_matched: Vec<&Transaction> = Vec::new();
+                       let mut indexes_of_txn_matched = Vec::new();
+                       for (idx, tx) in block.txdata.iter().enumerate() {
+                               if self.util.does_match_tx(&tx) {
+                                       txn_matched.push(tx);
+                                       indexes_of_txn_matched.push(idx as u32);
+                               }
+                       }
+                       //TODO: Height
+                       self.util.do_call_block_connected(&block.header, 0, &txn_matched[..], &indexes_of_txn_matched[..]);
+               }
+               self.chain.lock().unwrap().add_block(block);
+       }
+}
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644 (file)
index 0000000..3d2b94d
--- /dev/null
@@ -0,0 +1,12 @@
+#![crate_name = "lightning"]
+
+extern crate bitcoin;
+extern crate secp256k1;
+extern crate rand;
+extern crate crypto;
+extern crate num; //TODO: Convince andrew to not rely on this for fucking casting...
+
+pub mod chain;
+pub mod wallet;
+pub mod ln;
+pub mod util;
diff --git a/src/ln/chan_utils.rs b/src/ln/chan_utils.rs
new file mode 100644 (file)
index 0000000..b14f77e
--- /dev/null
@@ -0,0 +1,234 @@
+use bitcoin::blockdata::script::{Script,Builder};
+use bitcoin::blockdata::opcodes;
+use bitcoin::util::hash::Hash160;
+
+use secp256k1::key::{PublicKey,SecretKey};
+use secp256k1::Secp256k1;
+use secp256k1;
+
+use crypto::digest::Digest;
+use crypto::sha2::Sha256;
+use crypto::ripemd160::Ripemd160;
+
+// Various functions for key derivation and transaction creation for use within channels. Primarily
+// used in Channel and ChannelMonitor.
+
+pub fn build_commitment_secret(commitment_seed: [u8; 32], idx: u64) -> [u8; 32] {
+       let mut res: [u8; 32] = commitment_seed;
+       for i in 0..48 {
+               let bitpos = 47 - i;
+               if idx & (1 << bitpos) == (1 << bitpos) {
+                       res[bitpos / 8] ^= 1 << (bitpos & 7);
+                       let mut sha = Sha256::new();
+                       sha.input(&res);
+                       sha.result(&mut res);
+               }
+       }
+       res
+}
+
+pub fn derive_private_key(secp_ctx: &Secp256k1, per_commitment_point: &PublicKey, base_secret: &SecretKey) -> Result<SecretKey, secp256k1::Error> {
+       let mut sha = Sha256::new();
+       sha.input(&per_commitment_point.serialize());
+       sha.input(&PublicKey::from_secret_key(&secp_ctx, &base_secret).unwrap().serialize());
+       let mut res = [0; 32];
+       sha.result(&mut res);
+
+       let mut key = base_secret.clone();
+       try!(key.add_assign(&secp_ctx, &try!(SecretKey::from_slice(&secp_ctx, &res))));
+       Ok(key)
+}
+
+pub fn derive_public_key(secp_ctx: &Secp256k1, per_commitment_point: &PublicKey, base_point: &PublicKey) -> Result<PublicKey, secp256k1::Error> {
+       let mut sha = Sha256::new();
+       sha.input(&per_commitment_point.serialize());
+       sha.input(&base_point.serialize());
+       let mut res = [0; 32];
+       sha.result(&mut res);
+
+       let hashkey = PublicKey::from_secret_key(&secp_ctx, &try!(SecretKey::from_slice(&secp_ctx, &res))).unwrap();
+       base_point.combine(&secp_ctx, &hashkey)
+}
+
+/// Derives a revocation key from its constituent parts
+pub fn derive_private_revocation_key(secp_ctx: &Secp256k1, per_commitment_secret: &SecretKey, revocation_base_secret: &SecretKey) -> Result<SecretKey, secp256k1::Error> {
+       let revocation_base_point = PublicKey::from_secret_key(&secp_ctx, &revocation_base_secret).unwrap();
+       let per_commitment_point = PublicKey::from_secret_key(&secp_ctx, &per_commitment_secret).unwrap();
+
+       let rev_append_commit_hash_key = {
+               let mut sha = Sha256::new();
+               sha.input(&revocation_base_point.serialize());
+               sha.input(&per_commitment_point.serialize());
+               let mut res = [0; 32];
+               sha.result(&mut res);
+
+               try!(SecretKey::from_slice(&secp_ctx, &res))
+       };
+       let commit_append_rev_hash_key = {
+               let mut sha = Sha256::new();
+               sha.input(&per_commitment_point.serialize());
+               sha.input(&revocation_base_point.serialize());
+               let mut res = [0; 32];
+               sha.result(&mut res);
+
+               try!(SecretKey::from_slice(&secp_ctx, &res))
+       };
+
+       let mut part_a = revocation_base_secret.clone();
+       try!(part_a.mul_assign(&secp_ctx, &rev_append_commit_hash_key));
+       let mut part_b = per_commitment_secret.clone();
+       try!(part_b.mul_assign(&secp_ctx, &commit_append_rev_hash_key));
+       try!(part_a.add_assign(&secp_ctx, &part_b));
+       Ok(part_a)
+}
+
+pub fn derive_public_revocation_key(secp_ctx: &Secp256k1, per_commitment_point: &PublicKey, revocation_base_point: &PublicKey) -> Result<PublicKey, secp256k1::Error> {
+       let rev_append_commit_hash_key = {
+               let mut sha = Sha256::new();
+               sha.input(&revocation_base_point.serialize());
+               sha.input(&per_commitment_point.serialize());
+               let mut res = [0; 32];
+               sha.result(&mut res);
+
+               try!(SecretKey::from_slice(&secp_ctx, &res))
+       };
+       let commit_append_rev_hash_key = {
+               let mut sha = Sha256::new();
+               sha.input(&per_commitment_point.serialize());
+               sha.input(&revocation_base_point.serialize());
+               let mut res = [0; 32];
+               sha.result(&mut res);
+
+               try!(SecretKey::from_slice(&secp_ctx, &res))
+       };
+
+       let mut part_a = revocation_base_point.clone();
+       try!(part_a.mul_assign(&secp_ctx, &rev_append_commit_hash_key));
+       let mut part_b = per_commitment_point.clone();
+       try!(part_b.mul_assign(&secp_ctx, &commit_append_rev_hash_key));
+       part_a.combine(&secp_ctx, &part_b)
+}
+
+pub struct TxCreationKeys {
+       pub per_commitment_point: PublicKey,
+       pub revocation_key: PublicKey,
+       pub a_htlc_key: PublicKey,
+       pub b_htlc_key: PublicKey,
+       pub a_delayed_payment_key: PublicKey,
+       pub b_payment_key: PublicKey,
+}
+
+impl TxCreationKeys {
+       pub fn new(secp_ctx: &Secp256k1, per_commitment_point: &PublicKey, a_delayed_payment_base: &PublicKey, a_htlc_base: &PublicKey, b_revocation_base: &PublicKey, b_payment_base: &PublicKey, b_htlc_base: &PublicKey) -> Result<TxCreationKeys, secp256k1::Error> {
+               Ok(TxCreationKeys {
+                       per_commitment_point: per_commitment_point.clone(),
+                       revocation_key: try!(derive_public_revocation_key(&secp_ctx, &per_commitment_point, &b_revocation_base)),
+                       a_htlc_key: try!(derive_public_key(&secp_ctx, &per_commitment_point, &a_htlc_base)),
+                       b_htlc_key: try!(derive_public_key(&secp_ctx, &per_commitment_point, &b_htlc_base)),
+                       a_delayed_payment_key: try!(derive_public_key(&secp_ctx, &per_commitment_point, &a_delayed_payment_base)),
+                       b_payment_key: try!(derive_public_key(&secp_ctx, &per_commitment_point, &b_payment_base)),
+               })
+       }
+}
+
+/// Gets the "to_local" output redeemscript, ie the script which is time-locked or spendable by
+/// the revocation key
+pub fn get_revokeable_redeemscript(revocation_key: &PublicKey, to_self_delay: u16, delayed_payment_key: &PublicKey) -> Script {
+       Builder::new().push_opcode(opcodes::All::OP_IF)
+                                    .push_slice(&revocation_key.serialize())
+                                    .push_opcode(opcodes::All::OP_ELSE)
+                                    .push_int(to_self_delay as i64)
+                                    .push_opcode(opcodes::OP_CSV)
+                                    .push_opcode(opcodes::All::OP_DROP)
+                                    .push_slice(&delayed_payment_key.serialize())
+                                    .push_opcode(opcodes::All::OP_ENDIF)
+                                    .push_opcode(opcodes::All::OP_CHECKSIG)
+                                    .into_script()
+}
+
+#[derive(Clone)]
+pub struct HTLCOutputInCommitment {
+       pub offered: bool,
+       pub amount_msat: u64,
+       pub cltv_expiry: u32,
+       pub payment_hash: [u8; 32],
+       pub transaction_output_index: u32,
+}
+
+#[inline]
+pub fn get_htlc_redeemscript_with_explicit_keys(htlc: &HTLCOutputInCommitment, a_htlc_key: &PublicKey, b_htlc_key: &PublicKey, revocation_key: &PublicKey, offered: bool) -> Script {
+       let payment_hash160 = {
+               let mut ripemd = Ripemd160::new();
+               ripemd.input(&htlc.payment_hash);
+               let mut res = [0; 20];
+               ripemd.result(&mut res);
+               res
+       };
+       if offered {
+               Builder::new().push_opcode(opcodes::All::OP_DUP)
+                             .push_opcode(opcodes::All::OP_HASH160)
+                             .push_slice(&Hash160::from_data(&revocation_key.serialize())[..])
+                             .push_opcode(opcodes::All::OP_EQUAL)
+                             .push_opcode(opcodes::All::OP_IF)
+                             .push_opcode(opcodes::All::OP_CHECKSIG)
+                             .push_opcode(opcodes::All::OP_ELSE)
+                             .push_slice(&b_htlc_key.serialize()[..])
+                             .push_opcode(opcodes::All::OP_SWAP)
+                             .push_opcode(opcodes::All::OP_SIZE)
+                             .push_int(32)
+                             .push_opcode(opcodes::All::OP_EQUAL)
+                             .push_opcode(opcodes::All::OP_NOTIF)
+                             .push_opcode(opcodes::All::OP_DROP)
+                             .push_int(2)
+                             .push_opcode(opcodes::All::OP_SWAP)
+                             .push_slice(&a_htlc_key.serialize()[..])
+                             .push_int(2)
+                             .push_opcode(opcodes::All::OP_CHECKMULTISIG)
+                             .push_opcode(opcodes::All::OP_ELSE)
+                             .push_opcode(opcodes::All::OP_HASH160)
+                             .push_slice(&payment_hash160)
+                             .push_opcode(opcodes::All::OP_EQUALVERIFY)
+                             .push_opcode(opcodes::All::OP_CHECKSIG)
+                             .push_opcode(opcodes::All::OP_ENDIF)
+                             .push_opcode(opcodes::All::OP_ENDIF)
+                             .into_script()
+       } else {
+               Builder::new().push_opcode(opcodes::All::OP_DUP)
+                             .push_opcode(opcodes::All::OP_HASH160)
+                             .push_slice(&Hash160::from_data(&revocation_key.serialize())[..])
+                             .push_opcode(opcodes::All::OP_EQUAL)
+                             .push_opcode(opcodes::All::OP_IF)
+                             .push_opcode(opcodes::All::OP_CHECKSIG)
+                             .push_opcode(opcodes::All::OP_ELSE)
+                             .push_slice(&b_htlc_key.serialize()[..])
+                             .push_opcode(opcodes::All::OP_SWAP)
+                             .push_opcode(opcodes::All::OP_SIZE)
+                             .push_int(32)
+                             .push_opcode(opcodes::All::OP_EQUAL)
+                             .push_opcode(opcodes::All::OP_IF)
+                             .push_opcode(opcodes::All::OP_HASH160)
+                             .push_slice(&payment_hash160)
+                             .push_opcode(opcodes::All::OP_EQUALVERIFY)
+                             .push_int(2)
+                             .push_opcode(opcodes::All::OP_SWAP)
+                             .push_slice(&a_htlc_key.serialize()[..])
+                             .push_int(2)
+                             .push_opcode(opcodes::All::OP_CHECKMULTISIG)
+                             .push_opcode(opcodes::All::OP_ELSE)
+                             .push_opcode(opcodes::All::OP_DROP)
+                             .push_int(htlc.cltv_expiry as i64)
+                             .push_opcode(opcodes::OP_CLTV)
+                             .push_opcode(opcodes::All::OP_DROP)
+                             .push_opcode(opcodes::All::OP_CHECKSIG)
+                             .push_opcode(opcodes::All::OP_ENDIF)
+                             .push_opcode(opcodes::All::OP_ENDIF)
+                             .into_script()
+       }
+}
+
+/// note here that 'a_revocation_key' is generated using b_revocation_basepoint and a's
+/// commitment secret. 'htlc' does *not* need to have its previous_output_index filled.
+#[inline]
+pub fn get_htlc_redeemscript(htlc: &HTLCOutputInCommitment, keys: &TxCreationKeys, offered: bool) -> Script {
+       get_htlc_redeemscript_with_explicit_keys(htlc, &keys.a_htlc_key, &keys.b_htlc_key, &keys.revocation_key, offered)
+}
diff --git a/src/ln/channel.rs b/src/ln/channel.rs
new file mode 100644 (file)
index 0000000..054eed0
--- /dev/null
@@ -0,0 +1,2224 @@
+use bitcoin::blockdata::block::BlockHeader;
+use bitcoin::blockdata::script::{Script,Builder};
+use bitcoin::blockdata::transaction::{TxIn, TxOut, Transaction, SigHashType};
+use bitcoin::blockdata::opcodes;
+use bitcoin::util::uint::Uint256;
+use bitcoin::util::hash::{Sha256dHash, Hash160};
+use bitcoin::util::bip143;
+use bitcoin::network::serialize::BitcoinHash;
+
+use num::FromPrimitive;
+
+use secp256k1::key::{PublicKey,SecretKey};
+use secp256k1::{Secp256k1,Message,Signature};
+use secp256k1;
+
+use crypto::digest::Digest;
+use crypto::hkdf::{hkdf_extract,hkdf_expand};
+use crypto::sha2::Sha256;
+
+use ln::msgs;
+use ln::msgs::{HandleError, MsgEncodable};
+use ln::channelmonitor::ChannelMonitor;
+use ln::channelmanager::PendingForwardHTLCInfo;
+use ln::chan_utils::{TxCreationKeys,HTLCOutputInCommitment};
+use ln::chan_utils;
+use chain::chaininterface::{FeeEstimator,ConfirmationTarget};
+use util::transaction_utils;
+
+use rand::{thread_rng,Rng};
+
+use std::default::Default;
+use std::cmp;
+use std::time::Instant;
+
+pub struct ChannelKeys {
+       pub funding_key: SecretKey,
+       pub revocation_base_key: SecretKey,
+       pub payment_base_key: SecretKey,
+       pub delayed_payment_base_key: SecretKey,
+       pub htlc_base_key: SecretKey,
+       pub channel_close_key: SecretKey,
+       pub commitment_seed: [u8; 32],
+}
+
+impl ChannelKeys {
+       pub fn new_from_seed(seed: &[u8; 32]) -> Result<ChannelKeys, secp256k1::Error> {
+               let sha = Sha256::new();
+               let mut prk = [0; 32];
+               hkdf_extract(sha, b"rust-lightning key gen salt", seed, &mut prk);
+               let secp_ctx = Secp256k1::new();
+
+               let mut okm = [0; 32];
+               hkdf_expand(sha, &prk, b"rust-lightning funding key info", &mut okm);
+               let funding_key = try!(SecretKey::from_slice(&secp_ctx, &okm));
+
+               hkdf_expand(sha, &prk, b"rust-lightning revocation base key info", &mut okm);
+               let revocation_base_key = try!(SecretKey::from_slice(&secp_ctx, &okm));
+
+               hkdf_expand(sha, &prk, b"rust-lightning payment base key info", &mut okm);
+               let payment_base_key = try!(SecretKey::from_slice(&secp_ctx, &okm));
+
+               hkdf_expand(sha, &prk, b"rust-lightning delayed payment base key info", &mut okm);
+               let delayed_payment_base_key = try!(SecretKey::from_slice(&secp_ctx, &okm));
+
+               hkdf_expand(sha, &prk, b"rust-lightning htlc base key info", &mut okm);
+               let htlc_base_key = try!(SecretKey::from_slice(&secp_ctx, &okm));
+
+               hkdf_expand(sha, &prk, b"rust-lightning channel close key info", &mut okm);
+               let channel_close_key = try!(SecretKey::from_slice(&secp_ctx, &okm));
+
+               hkdf_expand(sha, &prk, b"rust-lightning local commitment seed info", &mut okm);
+
+               Ok(ChannelKeys {
+                       funding_key: funding_key,
+                       revocation_base_key: revocation_base_key,
+                       payment_base_key: payment_base_key,
+                       delayed_payment_base_key: delayed_payment_base_key,
+                       htlc_base_key: htlc_base_key,
+                       channel_close_key: channel_close_key,
+                       commitment_seed: okm
+               })
+       }
+}
+
+#[derive(PartialEq)]
+enum HTLCState {
+       RemoteAnnounced,
+       LocalAnnounced,
+       Committed,
+}
+
+struct HTLCOutput {
+       outbound: bool, // ie to an HTLC-Timeout transaction
+       htlc_id: u64,
+       amount_msat: u64,
+       cltv_expiry: u32,
+       payment_hash: [u8; 32],
+       state: HTLCState,
+       // state == RemoteAnnounced implies pending_forward_state, otherwise it must be None
+       pending_forward_state: Option<PendingForwardHTLCInfo>,
+}
+
+impl HTLCOutput {
+       fn get_in_commitment(&self, offered: bool) -> HTLCOutputInCommitment {
+               HTLCOutputInCommitment {
+                       offered: offered,
+                       amount_msat: self.amount_msat,
+                       cltv_expiry: self.cltv_expiry,
+                       payment_hash: self.payment_hash,
+                       transaction_output_index: 0
+               }
+       }
+}
+
+/// See AwaitingRemoteRevoke ChannelState for more info
+struct HTLCOutputAwaitingACK {
+       // always outbound
+       amount_msat: u64,
+       cltv_expiry: u32,
+       payment_hash: [u8; 32],
+       onion_routing_packet: msgs::OnionPacket,
+       time_created: Instant, //TODO: Some kind of timeout thing-a-majig
+}
+
+enum ChannelState {
+       /// Implies we have (or are prepared to) send our open_channel/accept_channel message
+       OurInitSent = (1 << 0),
+       /// Implies we have received their open_channel/accept_channel message
+       TheirInitSent = (1 << 1),
+       /// We have sent funding_created and are awaiting a funding_signed to advance to FundingSent.
+       /// Note that this is nonsense for an inbound channel as we immediately generate funding_signed
+       /// upon receipt of funding_created, so simply skip this state.
+       FundingCreated = 4,
+       /// Set when we have received/sent funding_created and funding_signed and are thus now waiting
+       /// on the funding transaction to confirm. The FundingLocked flags are set to indicate when we
+       /// and our counterparty consider the funding transaction confirmed.
+       FundingSent = 8,
+       /// Flag which can be set on FundingSent to indicate they sent us a funding_locked message.
+       /// Once both TheirFundingLocked and OurFundingLocked are set, state moves on to ChannelFunded.
+       TheirFundingLocked = (1 << 4),
+       /// Flag which can be set on FundingSent to indicate we sent them a funding_locked message.
+       /// Once both TheirFundingLocked and OurFundingLocked are set, state moves on to ChannelFunded.
+       OurFundingLocked = (1 << 5),
+       ChannelFunded = 64,
+       /// Flag which implies that we have sent a commitment_signed but are awaiting the responding
+       /// revoke_and_ack message. During this time period, we can't generate new commitment_signed
+       /// messages as then we will be unable to determine which HTLCs they included in their
+       /// revoke_and_ack implicit ACK, so instead we have to hold them away temporarily to be sent
+       /// later.
+       /// Flag is set on ChannelFunded.
+       AwaitingRemoteRevoke = (1 << 7),
+}
+
+// TODO: We should refactor this to be a Inbound/OutboundChannel until initial setup handshaking
+// has been completed, and then turn into a Channel to get compiler-time enforcement of things like
+// calling get_channel_id() before we're set up or things like get_outbound_funding_signed on an
+// inbound channel.
+pub struct Channel {
+       user_id: u64,
+
+       channel_id: Uint256,
+       channel_state: u32,
+       channel_outbound: bool,
+       secp_ctx: Secp256k1,
+       announce_publicly: bool,
+       channel_value_satoshis: u64,
+
+       local_keys: ChannelKeys,
+
+       cur_local_commitment_transaction_number: u64,
+       cur_remote_commitment_transaction_number: u64,
+       value_to_self_msat: u64, // Excluding all pending_htlcs, excluding fees
+       pending_htlcs: Vec<HTLCOutput>,
+       holding_cell_htlcs: Vec<HTLCOutputAwaitingACK>,
+       next_local_htlc_id: u64,
+       next_remote_htlc_id: u64,
+       channel_update_count: u32,
+       feerate_per_kw: u64,
+
+       /// The hash of the block in which the funding transaction reached our CONF_TARGET. We use this
+       /// to detect unconfirmation after a serialize-unserialize roudtrip where we may not see a full
+       /// series of block_connected/block_disconnected calls. Obviously this is not a guarantee as we
+       /// could miss the funding_tx_confirmed_in block as well, but it serves as a useful fallback.
+       funding_tx_confirmed_in: Sha256dHash,
+       short_channel_id: Option<u64>,
+       /// Used to deduplicate block_connected callbacks
+       last_block_connected: Sha256dHash,
+       funding_tx_confirmations: u64,
+
+       their_dust_limit_satoshis: u64,
+       our_dust_limit_satoshis: u64,
+       their_max_htlc_value_in_flight_msat: u64,
+       //get_our_max_htlc_value_in_flight_msat(): u64,
+       their_channel_reserve_satoshis: u64,
+       //get_our_channel_reserve_satoshis(): u64,
+       their_htlc_minimum_msat: u64,
+       our_htlc_minimum_msat: u64,
+       their_to_self_delay: u16,
+       //implied by BREAKDOWN_TIMEOUT: our_to_self_delay: u16,
+       their_max_accepted_htlcs: u16,
+       //implied by OUR_MAX_HTLCS: our_max_accepted_htlcs: u16,
+
+       their_funding_pubkey: PublicKey,
+       their_revocation_basepoint: PublicKey,
+       their_payment_basepoint: PublicKey,
+       their_delayed_payment_basepoint: PublicKey,
+       their_htlc_basepoint: PublicKey,
+       their_cur_commitment_point: PublicKey,
+       their_node_id: PublicKey,
+
+       channel_monitor: ChannelMonitor,
+}
+
+const OUR_MAX_HTLCS: u16 = 1; //TODO
+const CONF_TARGET: u32 = 12; //TODO: Should be much higher
+/// Confirmation count threshold at which we close a channel. Ideally we'd keep the channel around
+/// on ice until the funding transaction gets more confirmations, but the LN protocol doesn't
+/// really allow for this, so instead we're stuck closing it out at that point.
+const UNCONF_THRESHOLD: u32 = 6;
+/// The amount of time we require our counterparty wait to claim their money (ie time between when
+/// we, or our watchtower, must check for them having broadcast a theft transaction).
+const BREAKDOWN_TIMEOUT: u16 = 6 * 24 * 7; //TODO?
+/// The amount of time we're willing to wait to claim money back to us
+const MAX_LOCAL_BREAKDOWN_TIMEOUT: u16 = 6 * 24 * 14;
+const COMMITMENT_TX_BASE_WEIGHT: u64 = 724;
+const COMMITMENT_TX_WEIGHT_PER_HTLC: u64 = 172;
+const HTLC_SUCCESS_TX_WEIGHT: u64 = 703;
+const HTLC_TIMEOUT_TX_WEIGHT: u64 = 663;
+const SPENDING_INPUT_FOR_A_OUTPUT_WEIGHT: u64 = 79; // prevout: 36, nSequence: 4, script len: 1, witness lengths: (3+1)/4, sig: 73/4, if-selector: 1, redeemScript: (6 ops + 2*33 pubkeys + 1*2 delay)/4
+const B_OUTPUT_PLUS_SPENDING_INPUT_WEIGHT: u64 = 104; // prevout: 40, nSequence: 4, script len: 1, witness lengths: 3/4, sig: 73/4, pubkey: 33/4, output: 31 (TODO: Wrong? Useless?)
+
+macro_rules! secp_call {
+       ( $res : expr ) => {
+               match $res {
+                       Ok(key) => key,
+                       //TODO: make the error a parameter
+                       Err(_) => return Err(HandleError{err: "Secp call failed - probably bad signature or evil data generated a bad pubkey/privkey", msg: None})
+               }
+       };
+}
+
+macro_rules! get_key {
+       ( $ctx : expr, $slice : expr ) => {
+               secp_call! (SecretKey::from_slice($ctx, $slice))
+       };
+}
+
+impl Channel {
+       // Convert constants + channel value to limits:
+       fn get_our_max_htlc_value_in_flight_msat(channel_value_satoshis: u64) -> u64 {
+               channel_value_satoshis * 1000 / 10 //TODO
+       }
+
+       /// Guaranteed to return a value no larger than channel_value_satoshis
+       fn get_our_channel_reserve_satoshis(channel_value_satoshis: u64) -> u64 {
+               cmp::min(channel_value_satoshis, 10) //TODO
+       }
+
+       fn derive_our_dust_limit_satoshis(at_open_background_feerate: u64) -> u64 {
+               at_open_background_feerate * B_OUTPUT_PLUS_SPENDING_INPUT_WEIGHT //TODO
+       }
+
+       fn derive_our_htlc_minimum_msat(_at_open_channel_feerate_per_kw: u64) -> u64 {
+               1000 // TODO
+       }
+
+       // Constructors:
+
+       /// panics if channel_value_satoshis is >= (1 << 24)
+       pub fn new_outbound(fee_estimator: &FeeEstimator, their_node_id: PublicKey, channel_value_satoshis: u64, announce_publicly: bool, user_id: u64) -> Channel {
+               if channel_value_satoshis >= (1 << 24) {
+                       panic!("funding value > 2^24");
+               }
+
+               let mut rng = thread_rng();
+               let feerate = fee_estimator.get_est_sat_per_vbyte(ConfirmationTarget::Normal);
+               let background_feerate = fee_estimator.get_est_sat_per_vbyte(ConfirmationTarget::Background);
+
+               let mut key_seed = [0u8; 32];
+               rng.fill_bytes(&mut key_seed);
+               let chan_keys = match ChannelKeys::new_from_seed(&key_seed) {
+                       Ok(key) => key,
+                       Err(_) => panic!("RNG is busted!")
+               };
+
+               let secp_ctx = Secp256k1::new();
+               let our_channel_close_key_hash = Hash160::from_data(&PublicKey::from_secret_key(&secp_ctx, &chan_keys.channel_close_key).unwrap().serialize());
+               let our_channel_monitor_claim_script = Builder::new().push_opcode(opcodes::All::OP_PUSHBYTES_0).push_slice(&our_channel_close_key_hash[..]).into_script();
+               let channel_monitor = ChannelMonitor::new(&chan_keys.revocation_base_key,
+                                                         &PublicKey::from_secret_key(&secp_ctx, &chan_keys.delayed_payment_base_key).unwrap(),
+                                                         &PublicKey::from_secret_key(&secp_ctx, &chan_keys.htlc_base_key).unwrap(),
+                                                         BREAKDOWN_TIMEOUT, our_channel_monitor_claim_script);
+
+               Channel {
+                       user_id: user_id,
+
+                       channel_id: Uint256([rng.gen(), rng.gen(), rng.gen(), rng.gen()]),
+                       channel_state: ChannelState::OurInitSent as u32,
+                       channel_outbound: true,
+                       secp_ctx: secp_ctx,
+                       announce_publicly: announce_publicly,
+                       channel_value_satoshis: channel_value_satoshis,
+
+                       local_keys: chan_keys,
+                       cur_local_commitment_transaction_number: (1 << 48) - 1,
+                       cur_remote_commitment_transaction_number: (1 << 48) - 1,
+                       value_to_self_msat: channel_value_satoshis * 1000, //TODO: give them something on open? Parameterize it?
+                       pending_htlcs: Vec::new(),
+                       holding_cell_htlcs: Vec::new(),
+                       next_local_htlc_id: 0,
+                       next_remote_htlc_id: 0,
+                       channel_update_count: 0,
+
+                       funding_tx_confirmed_in: Default::default(),
+                       short_channel_id: None,
+                       last_block_connected: Default::default(),
+                       funding_tx_confirmations: 0,
+
+                       feerate_per_kw: feerate * 250,
+                       their_dust_limit_satoshis: 0,
+                       our_dust_limit_satoshis: Channel::derive_our_dust_limit_satoshis(background_feerate),
+                       their_max_htlc_value_in_flight_msat: 0,
+                       their_channel_reserve_satoshis: 0,
+                       their_htlc_minimum_msat: 0,
+                       our_htlc_minimum_msat: Channel::derive_our_htlc_minimum_msat(feerate * 250),
+                       their_to_self_delay: 0,
+                       their_max_accepted_htlcs: 0,
+
+                       their_funding_pubkey: PublicKey::new(),
+                       their_revocation_basepoint: PublicKey::new(),
+                       their_payment_basepoint: PublicKey::new(),
+                       their_delayed_payment_basepoint: PublicKey::new(),
+                       their_htlc_basepoint: PublicKey::new(),
+                       their_cur_commitment_point: PublicKey::new(),
+                       their_node_id: their_node_id,
+
+                       channel_monitor: channel_monitor,
+               }
+       }
+
+       fn check_remote_fee(fee_estimator: &FeeEstimator, feerate_per_kw: u32) -> Result<(), HandleError> {
+               if (feerate_per_kw as u64) < fee_estimator.get_est_sat_per_vbyte(ConfirmationTarget::Background) * 250 {
+                       return Err(HandleError{err: "Peer's feerate much too low", msg: None});
+               }
+               if (feerate_per_kw as u64) > fee_estimator.get_est_sat_per_vbyte(ConfirmationTarget::HighPriority) * 375 { // 375 = 250 * 1.5x
+                       return Err(HandleError{err: "Peer's feerate much too high", msg: None});
+               }
+               Ok(())
+       }
+
+       /// Creates a new channel from a remote sides' request for one.
+       /// Assumes chain_hash has already been checked and corresponds with what we expect!
+       pub fn new_from_req(fee_estimator: &FeeEstimator, their_node_id: PublicKey, msg: &msgs::OpenChannel, user_id: u64, announce_publicly: bool) -> Result<Channel, HandleError> {
+               // Check sanity of message fields:
+               if msg.funding_satoshis >= (1 << 24) {
+                       return Err(HandleError{err: "funding value > 2^24", msg: None});
+               }
+               if msg.funding_satoshis > 21000000 * 100000000 {
+                       return Err(HandleError{err: "More funding_satoshis than there are satoshis!", msg: None});
+               }
+               if msg.channel_reserve_satoshis > msg.funding_satoshis {
+                       return Err(HandleError{err: "Bogus channel_reserve_satoshis", msg: None});
+               }
+               if msg.push_msat > (msg.funding_satoshis - msg.channel_reserve_satoshis) * 1000 {
+                       return Err(HandleError{err: "push_msat more than highest possible value", msg: None});
+               }
+               //TODO Check if dust_limit is sane?
+               if msg.max_htlc_value_in_flight_msat > msg.funding_satoshis * 1000 {
+                       return Err(HandleError{err: "Bogus max_htlc_value_in_flight_satoshis", msg: None});
+               }
+               if msg.htlc_minimum_msat >= (msg.funding_satoshis - msg.channel_reserve_satoshis) * 1000 {
+                       return Err(HandleError{err: "Minimum htlc value is full channel value", msg: None});
+               }
+               Channel::check_remote_fee(fee_estimator, msg.feerate_per_kw).unwrap();
+               if msg.to_self_delay > MAX_LOCAL_BREAKDOWN_TIMEOUT {
+                       return Err(HandleError{err: "They wanted our payments to be delayed by a needlessly long period", msg: None});
+               }
+               if msg.max_accepted_htlcs < 1 {
+                       return Err(HandleError{err: "0 max_accpted_htlcs makes for a useless channel", msg: None});
+               }
+               if (msg.channel_flags & 254) != 0 {
+                       return Err(HandleError{err: "unknown channel_flags", msg: None});
+               }
+
+               // Convert things into internal flags and prep our state:
+
+               let their_announce = if (msg.channel_flags & 1) == 1 { true } else { false };
+
+               let background_feerate = fee_estimator.get_est_sat_per_vbyte(ConfirmationTarget::Background);
+
+               let mut rng = thread_rng();
+               let mut key_seed = [0u8; 32];
+               rng.fill_bytes(&mut key_seed);
+               let chan_keys = match ChannelKeys::new_from_seed(&key_seed) {
+                       Ok(key) => key,
+                       Err(_) => panic!("RNG is busted!")
+               };
+
+               let secp_ctx = Secp256k1::new();
+               let our_channel_close_key_hash = Hash160::from_data(&PublicKey::from_secret_key(&secp_ctx, &chan_keys.channel_close_key).unwrap().serialize());
+               let our_channel_monitor_claim_script = Builder::new().push_opcode(opcodes::All::OP_PUSHBYTES_0).push_slice(&our_channel_close_key_hash[..]).into_script();
+               let mut channel_monitor = ChannelMonitor::new(&chan_keys.revocation_base_key,
+                                                         &PublicKey::from_secret_key(&secp_ctx, &chan_keys.delayed_payment_base_key).unwrap(),
+                                                         &PublicKey::from_secret_key(&secp_ctx, &chan_keys.htlc_base_key).unwrap(),
+                                                         BREAKDOWN_TIMEOUT, our_channel_monitor_claim_script);
+               channel_monitor.set_their_htlc_base_key(&msg.htlc_basepoint);
+
+               let mut chan = Channel {
+                       user_id: user_id,
+
+                       channel_id: msg.temporary_channel_id,
+                       channel_state: (ChannelState::OurInitSent as u32) | (ChannelState::TheirInitSent as u32),
+                       channel_outbound: false,
+                       secp_ctx: secp_ctx,
+                       announce_publicly: their_announce && announce_publicly,
+
+                       local_keys: chan_keys,
+                       cur_local_commitment_transaction_number: (1 << 48) - 1,
+                       cur_remote_commitment_transaction_number: (1 << 48) - 1,
+                       value_to_self_msat: msg.push_msat,
+                       pending_htlcs: Vec::new(),
+                       holding_cell_htlcs: Vec::new(),
+                       next_local_htlc_id: 0,
+                       next_remote_htlc_id: 0,
+                       channel_update_count: 0,
+
+                       funding_tx_confirmed_in: Default::default(),
+                       short_channel_id: None,
+                       last_block_connected: Default::default(),
+                       funding_tx_confirmations: 0,
+
+                       feerate_per_kw: msg.feerate_per_kw as u64,
+                       channel_value_satoshis: msg.funding_satoshis,
+                       their_dust_limit_satoshis: msg.dust_limit_satoshis,
+                       our_dust_limit_satoshis: Channel::derive_our_dust_limit_satoshis(background_feerate),
+                       their_max_htlc_value_in_flight_msat: msg.max_htlc_value_in_flight_msat,
+                       their_channel_reserve_satoshis: msg.channel_reserve_satoshis,
+                       their_htlc_minimum_msat: msg.htlc_minimum_msat,
+                       our_htlc_minimum_msat: Channel::derive_our_htlc_minimum_msat(msg.feerate_per_kw as u64),
+                       their_to_self_delay: msg.to_self_delay,
+                       their_max_accepted_htlcs: msg.max_accepted_htlcs,
+
+                       their_funding_pubkey: msg.funding_pubkey,
+                       their_revocation_basepoint: msg.revocation_basepoint,
+                       their_payment_basepoint: msg.payment_basepoint,
+                       their_delayed_payment_basepoint: msg.delayed_payment_basepoint,
+                       their_htlc_basepoint: msg.htlc_basepoint,
+                       their_cur_commitment_point: msg.first_per_commitment_point,
+                       their_node_id: their_node_id,
+
+                       channel_monitor: channel_monitor,
+               };
+
+               let obscure_factor = chan.get_commitment_transaction_number_obscure_factor();
+               chan.channel_monitor.set_commitment_obscure_factor(obscure_factor);
+
+               Ok(chan)
+       }
+
+       // Utilities to derive keys:
+
+       fn build_local_commitment_secret(&self, idx: u64) -> Result<SecretKey, HandleError> {
+               let res = chan_utils::build_commitment_secret(self.local_keys.commitment_seed, idx);
+               Ok(get_key!(&self.secp_ctx, &res))
+       }
+
+       // Utilities to build transactions:
+
+       fn get_commitment_transaction_number_obscure_factor(&self) -> u64 {
+               let mut sha = Sha256::new();
+               let our_payment_basepoint = PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.payment_base_key).unwrap();
+
+               if self.channel_outbound {
+                       sha.input(&our_payment_basepoint.serialize());
+                       sha.input(&self.their_payment_basepoint.serialize());
+               } else {
+                       sha.input(&self.their_payment_basepoint.serialize());
+                       sha.input(&our_payment_basepoint.serialize());
+               }
+               let mut res = [0; 32];
+               sha.result(&mut res);
+
+               ((res[26] as u64) << 5*8) |
+               ((res[27] as u64) << 4*8) |
+               ((res[28] as u64) << 3*8) |
+               ((res[29] as u64) << 2*8) |
+               ((res[30] as u64) << 1*8) |
+               ((res[31] as u64) << 0*8)
+       }
+
+       /// Transaction nomenclature is somewhat confusing here as there are many different cases - a
+       /// transaction is referred to as "a's transaction" implying that a will be able to broadcast
+       /// the transaction. Thus, b will generally be sending a signature over such a transaction to
+       /// a, and a can revoke the transaction by providing b the relevant per_commitment_secret. As
+       /// such, a transaction is generally the result of b increasing the amount paid to a (or adding
+       /// an HTLC to a).
+       /// @local is used only to convert relevant internal structures which refer to remote vs local
+       /// to decide value of outputs and direction of HTLCs.
+       /// @generated_by_local is used to determine *which* HTLCs to include - noting that the HTLC
+       /// state may indicate that one peer has informed the other that they'd like to add an HTLC but
+       /// have not yet committed it. Such HTLCs will only be included in transactions which are being
+       /// generated by the peer which proposed adding the HTLCs, and thus we need to understand both
+       /// which peer generated this transaction and "to whom" this transaction flows.
+       #[inline]
+       fn build_commitment_transaction(&self, commitment_number: u64, keys: &TxCreationKeys, local: bool, generated_by_local: bool) -> Result<(Transaction, Vec<HTLCOutputInCommitment>), HandleError> {
+               let obscured_commitment_transaction_number = self.get_commitment_transaction_number_obscure_factor() ^ commitment_number;
+
+               let txins = {
+                       let mut ins: Vec<TxIn> = Vec::new();
+                       ins.push(TxIn {
+                               prev_hash: self.channel_monitor.get_funding_txo().unwrap().0,
+                               prev_index: self.channel_monitor.get_funding_txo().unwrap().1 as u32,
+                               script_sig: Script::new(),
+                               sequence: ((0x80 as u32) << 8*3) | ((obscured_commitment_transaction_number >> 3*8) as u32)
+                       });
+                       ins
+               };
+               let mut witness: Vec<Vec<Vec<u8>>> = Vec::new();
+               witness.push(Vec::new());
+
+               let mut txouts: Vec<(TxOut, Option<HTLCOutputInCommitment>)> = Vec::new();
+
+               let dust_limit_satoshis = if local { self.our_dust_limit_satoshis } else { self.their_dust_limit_satoshis };
+               let mut remote_htlc_total_msat = 0;
+               let mut local_htlc_total_msat = 0;
+
+               for ref htlc in self.pending_htlcs.iter() {
+                       if htlc.state == HTLCState::Committed || htlc.state == (if generated_by_local { HTLCState::LocalAnnounced } else { HTLCState::RemoteAnnounced }) {
+                               if htlc.outbound == local { // "offered HTLC output"
+                                       if htlc.amount_msat / 1000 >= dust_limit_satoshis + (self.feerate_per_kw * HTLC_TIMEOUT_TX_WEIGHT / 1000) {
+                                               let htlc_in_tx = htlc.get_in_commitment(true);
+                                               txouts.push((TxOut {
+                                                       script_pubkey: chan_utils::get_htlc_redeemscript(&htlc_in_tx, &keys, true).to_v0_p2wsh(),
+                                                       value: htlc.amount_msat / 1000
+                                               }, Some(htlc_in_tx)));
+                                       }
+                               } else {
+                                       if htlc.amount_msat / 1000 >= dust_limit_satoshis + (self.feerate_per_kw * HTLC_SUCCESS_TX_WEIGHT / 1000) {
+                                               let htlc_in_tx = htlc.get_in_commitment(false);
+                                               txouts.push((TxOut { // "received HTLC output"
+                                                       script_pubkey: chan_utils::get_htlc_redeemscript(&htlc_in_tx, &keys, false).to_v0_p2wsh(),
+                                                       value: htlc.amount_msat / 1000
+                                               }, Some(htlc_in_tx)));
+                                       }
+                               };
+                               if htlc.outbound {
+                                       local_htlc_total_msat += htlc.amount_msat;
+                               } else {
+                                       remote_htlc_total_msat += htlc.amount_msat;
+                               }
+                       }
+               }
+
+               let total_fee: u64 = self.feerate_per_kw * (COMMITMENT_TX_BASE_WEIGHT + (txouts.len() as u64) * COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000;
+               let value_to_self: i64 = ((self.value_to_self_msat - local_htlc_total_msat) as i64) / 1000 - if self.channel_outbound { total_fee as i64 } else { 0 };
+               let value_to_remote: i64 = (((self.channel_value_satoshis * 1000 - self.value_to_self_msat - remote_htlc_total_msat) / 1000) as i64) - if self.channel_outbound { 0 } else { total_fee as i64 };
+
+               let value_to_a = if local { value_to_self } else { value_to_remote };
+               let value_to_b = if local { value_to_remote } else { value_to_self };
+
+               if value_to_a >= (dust_limit_satoshis as i64) {
+                       txouts.push((TxOut {
+                               script_pubkey: chan_utils::get_revokeable_redeemscript(&keys.revocation_key,
+                                                                                      if local { self.their_to_self_delay } else { BREAKDOWN_TIMEOUT },
+                                                                                      &keys.a_delayed_payment_key).to_v0_p2wsh(),
+                               value: value_to_a as u64
+                       }, None));
+               }
+
+               if value_to_b >= (dust_limit_satoshis as i64) {
+                       txouts.push((TxOut {
+                               script_pubkey: Builder::new().push_opcode(opcodes::All::OP_PUSHBYTES_0)
+                                                            .push_slice(&Hash160::from_data(&keys.b_payment_key.serialize())[..])
+                                                            .into_script(),
+                               value: value_to_b as u64
+                       }, None));
+               }
+
+               transaction_utils::sort_outputs(&mut txouts);
+
+               let mut outputs: Vec<TxOut> = Vec::new();
+               let mut htlcs_used: Vec<HTLCOutputInCommitment> = Vec::new();
+               for (idx, out) in txouts.drain(..).enumerate() {
+                       outputs.push(out.0);
+                       match out.1 {
+                               Some(out_htlc) => {
+                                       htlcs_used.push(out_htlc);
+                                       htlcs_used.last_mut().unwrap().transaction_output_index = idx as u32;
+                               },
+                               None => {}
+                       }
+               }
+
+               Ok((Transaction {
+                       version: 2,
+                       lock_time: ((0x20 as u32) << 8*3) | ((obscured_commitment_transaction_number & 0xffffffu64) as u32),
+                       input: txins,
+                       output: outputs,
+                       witness: witness
+               }, htlcs_used))
+       }
+
+       #[inline]
+       /// Creates a set of keys for build_commitment_transaction to generate a transaction which our
+       /// counterparty will sign (ie DO NOT send signatures over a transaction created by this to
+       /// our counterparty!)
+       /// The result is a transaction which we can revoke ownership of (ie a "local" transaction)
+       /// TODO Some magic rust shit to compile-time check this?
+       fn build_local_transaction_keys(&self, commitment_number: u64) -> Result<TxCreationKeys, HandleError> {
+               let per_commitment_point = PublicKey::from_secret_key(&self.secp_ctx, &try!(self.build_local_commitment_secret(commitment_number))).unwrap();
+               let delayed_payment_base = PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.delayed_payment_base_key).unwrap();
+               let htlc_basepoint = PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.htlc_base_key).unwrap();
+
+               Ok(secp_call!(TxCreationKeys::new(&self.secp_ctx, &per_commitment_point, &delayed_payment_base, &htlc_basepoint, &self.their_revocation_basepoint, &self.their_payment_basepoint, &self.their_htlc_basepoint)))
+       }
+
+       #[inline]
+       /// Creates a set of keys for build_commitment_transaction to generate a transaction which we
+       /// will sign and send to our counterparty.
+       fn build_remote_transaction_keys(&self) -> Result<TxCreationKeys, HandleError> {
+               //TODO: Ensure that the payment_key derived here ends up in the library users' wallet as we
+               //may see payments to it!
+               let payment_basepoint = PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.payment_base_key).unwrap();
+               let revocation_basepoint = PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.revocation_base_key).unwrap();
+               let htlc_basepoint = PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.htlc_base_key).unwrap();
+
+               Ok(secp_call!(TxCreationKeys::new(&self.secp_ctx, &self.their_cur_commitment_point, &self.their_delayed_payment_basepoint, &self.their_htlc_basepoint, &revocation_basepoint, &payment_basepoint, &htlc_basepoint)))
+       }
+
+       /// Gets the redeemscript for the funding transaction output (ie the funding transaction output
+       /// pays to get_funding_redeemscript().to_v0_p2wsh()).
+       pub fn get_funding_redeemscript(&self) -> Script {
+               let builder = Builder::new().push_opcode(opcodes::All::OP_PUSHNUM_2);
+               let our_funding_key = PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.funding_key).unwrap().serialize();
+               let their_funding_key = self.their_funding_pubkey.serialize();
+               if our_funding_key[..] < their_funding_key[..] {
+                       builder.push_slice(&our_funding_key)
+                               .push_slice(&their_funding_key)
+               } else {
+                       builder.push_slice(&their_funding_key)
+                               .push_slice(&our_funding_key)
+               }.push_opcode(opcodes::All::OP_PUSHNUM_2).push_opcode(opcodes::All::OP_CHECKMULTISIG).into_script()
+       }
+
+       fn sign_commitment_transaction(&self, tx: &mut Transaction, their_sig: &Signature) -> Result<(), HandleError> {
+               if tx.input.len() != 1 {
+                       panic!("Tried to sign commitment transaction that had input count != 1!");
+               }
+               if tx.witness.len() != 1 || tx.witness[0].len() != 0 {
+                       panic!("Tried to re-sign commitment transaction");
+               }
+
+               let funding_redeemscript = self.get_funding_redeemscript();
+
+               let sighash = secp_call!(Message::from_slice(&bip143::SighashComponents::new(&tx).sighash_all(&tx, 0, &funding_redeemscript, self.channel_value_satoshis)[..]));
+               let our_sig = secp_call!(self.secp_ctx.sign(&sighash, &self.local_keys.funding_key));
+
+               tx.witness[0].push(Vec::new()); // First is the multisig dummy
+
+               let our_funding_key = PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.funding_key).unwrap().serialize();
+               let their_funding_key = self.their_funding_pubkey.serialize();
+               if our_funding_key[..] < their_funding_key[..] {
+                       tx.witness[0].push(our_sig.serialize_der(&self.secp_ctx).to_vec());
+                       tx.witness[0].push(their_sig.serialize_der(&self.secp_ctx).to_vec());
+               } else {
+                       tx.witness[0].push(their_sig.serialize_der(&self.secp_ctx).to_vec());
+                       tx.witness[0].push(our_sig.serialize_der(&self.secp_ctx).to_vec());
+               }
+               tx.witness[0][1].push(SigHashType::All as u8);
+               tx.witness[0][2].push(SigHashType::All as u8);
+
+               tx.witness[0].push(funding_redeemscript.into_vec());
+
+               Ok(())
+       }
+
+       /// Builds the htlc-success or htlc-timeout transaction which spends a given HTLC output
+       /// @local is used only to convert relevant internal structures which refer to remote vs local
+       /// to decide value of outputs and direction of HTLCs.
+       fn build_htlc_transaction(&self, prev_hash: &Sha256dHash, htlc: &HTLCOutputInCommitment, local: bool, keys: &TxCreationKeys) -> Result<Transaction, HandleError> {
+               let mut txins: Vec<TxIn> = Vec::new();
+               txins.push(TxIn {
+                       prev_hash: prev_hash.clone(),
+                       prev_index: htlc.transaction_output_index,
+                       script_sig: Script::new(),
+                       sequence: 0
+               });
+
+               let mut witnesses: Vec<Vec<Vec<u8>>> = Vec::new();
+               witnesses.push(Vec::new());
+
+               let total_fee = if htlc.offered {
+                               self.feerate_per_kw * HTLC_TIMEOUT_TX_WEIGHT / 1000
+                       } else {
+                               self.feerate_per_kw * HTLC_SUCCESS_TX_WEIGHT / 1000
+                       };
+
+               let mut txouts: Vec<TxOut> = Vec::new();
+               txouts.push(TxOut {
+                       script_pubkey: chan_utils::get_revokeable_redeemscript(&keys.revocation_key,
+                                                                              if local { self.their_to_self_delay } else { BREAKDOWN_TIMEOUT },
+                                                                              &keys.a_delayed_payment_key).to_v0_p2wsh(),
+                       value: htlc.amount_msat / 1000 - total_fee //TODO: BOLT 3 does not specify if we should add amount_msat before dividing or if we should divide by 1000 before subtracting (as we do here)
+               });
+
+               Ok(Transaction {
+                       version: 2,
+                       lock_time: if htlc.offered { htlc.cltv_expiry } else { 0 },
+                       input: txins,
+                       output: txouts,
+                       witness: witnesses
+               })
+       }
+
+       /// Signs a transaction created by build_htlc_transaction. If the transaction is an
+       /// HTLC-Success transaction (ie htlc.offered is false), preimate must be set!
+       fn sign_htlc_transaction(&self, tx: &mut Transaction, their_sig: &Signature, preimage: &Option<[u8; 32]>, htlc: &HTLCOutputInCommitment, keys: &TxCreationKeys) -> Result<(), HandleError> {
+               if tx.input.len() != 1 {
+                       panic!("Tried to sign HTLC transaction that had input count != 1!");
+               }
+               if tx.witness.len() != 1 || tx.witness[0].len() != 0 {
+                       panic!("Tried to re-sign HTLC transaction");
+               }
+
+               let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &keys, htlc.offered);
+
+               let our_htlc_key = secp_call!(chan_utils::derive_private_key(&self.secp_ctx, &keys.per_commitment_point, &self.local_keys.htlc_base_key));
+               let sighash = secp_call!(Message::from_slice(&bip143::SighashComponents::new(&tx).sighash_all(&tx, 0, &htlc_redeemscript, htlc.amount_msat / 1000)[..]));
+               let our_sig = secp_call!(self.secp_ctx.sign(&sighash, &our_htlc_key));
+
+               let local_tx = PublicKey::from_secret_key(&self.secp_ctx, &our_htlc_key).unwrap() == keys.a_htlc_key;
+
+               tx.witness[0].push(Vec::new()); // First is the multisig dummy
+
+               if local_tx { // b, then a
+                       tx.witness[0].push(their_sig.serialize_der(&self.secp_ctx).to_vec());
+                       tx.witness[0].push(our_sig.serialize_der(&self.secp_ctx).to_vec());
+               } else {
+                       tx.witness[0].push(our_sig.serialize_der(&self.secp_ctx).to_vec());
+                       tx.witness[0].push(their_sig.serialize_der(&self.secp_ctx).to_vec());
+               }
+               tx.witness[0][1].push(SigHashType::All as u8);
+               tx.witness[0][2].push(SigHashType::All as u8);
+
+               if htlc.offered {
+                       tx.witness[0].push(Vec::new());
+               } else {
+                       tx.witness[0].push(preimage.unwrap().to_vec());
+               }
+
+               tx.witness[0].push(htlc_redeemscript.into_vec());
+
+               Ok(())
+       }
+
+       pub fn get_update_fulfill_htlc(&mut self, payment_preimage: [u8; 32]) -> Result<msgs::UpdateFulfillHTLC, HandleError> {
+               if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) {
+                       return Err(HandleError{err: "Was asked to fulfill an HTLC when channel was not in an operational state", msg: None});
+               }
+
+               let mut sha = Sha256::new();
+               sha.input(&payment_preimage);
+               let mut payment_hash = [0; 32];
+               sha.result(&mut payment_hash);
+
+               let mut htlc_id = 0;
+               let mut htlc_amount_msat = 0;
+               self.pending_htlcs.retain(|ref htlc| {
+                       if !htlc.outbound && htlc.payment_hash == payment_hash {
+                               if htlc_id != 0 {
+                                       panic!("Duplicate HTLC payment_hash, you probably re-used payment preimages, NEVER DO THIS!");
+                               }
+                               htlc_id = htlc.htlc_id;
+                               htlc_amount_msat += htlc.amount_msat;
+                               false
+                       } else { true }
+               });
+               if htlc_amount_msat == 0 {
+                       return Err(HandleError{err: "Unable to find a pending HTLC which matched the given payment preimage", msg: None});
+               }
+
+               self.value_to_self_msat += htlc_amount_msat;
+
+               Ok(msgs::UpdateFulfillHTLC {
+                       channel_id: self.channel_id(),
+                       htlc_id: htlc_id,
+                       payment_preimage: payment_preimage,
+               })
+       }
+
+       // Message handlers:
+
+       pub fn accept_channel(&mut self, msg: &msgs::AcceptChannel) -> Result<(), HandleError> {
+               // Check sanity of message fields:
+               //TODO Check if dust_limit is sane?
+               if !self.channel_outbound {
+                       return Err(HandleError{err: "Got an accept_channel message from an inbound peer", msg: None});
+               }
+               if self.channel_state != ChannelState::OurInitSent as u32 {
+                       return Err(HandleError{err: "Got an accept_channel message at a strange time", msg: None});
+               }
+               if msg.max_htlc_value_in_flight_msat > self.channel_value_satoshis * 1000 {
+                       return Err(HandleError{err: "Bogus max_htlc_value_in_flight_satoshis", msg: None});
+               }
+               if msg.channel_reserve_satoshis > self.channel_value_satoshis {
+                       return Err(HandleError{err: "Bogus channel_reserve_satoshis", msg: None});
+               }
+               if msg.htlc_minimum_msat >= (self.channel_value_satoshis - msg.channel_reserve_satoshis) * 1000 {
+                       return Err(HandleError{err: "Minimum htlc value is full channel value", msg: None});
+               }
+               //TODO do something with minimum_depth
+               if msg.to_self_delay > MAX_LOCAL_BREAKDOWN_TIMEOUT {
+                       return Err(HandleError{err: "They wanted our payments to be delayed by a needlessly long period", msg: None});
+               }
+               if msg.max_accepted_htlcs < 1 {
+                       return Err(HandleError{err: "0 max_accpted_htlcs makes for a useless channel", msg: None});
+               }
+
+               self.channel_monitor.set_their_htlc_base_key(&msg.htlc_basepoint);
+
+               self.their_dust_limit_satoshis = msg.dust_limit_satoshis;
+               self.their_max_htlc_value_in_flight_msat = msg.max_htlc_value_in_flight_msat;
+               self.their_channel_reserve_satoshis = msg.channel_reserve_satoshis;
+               self.their_htlc_minimum_msat = msg.htlc_minimum_msat;
+               self.their_to_self_delay = msg.to_self_delay;
+               self.their_max_accepted_htlcs = msg.max_accepted_htlcs;
+               self.their_funding_pubkey = msg.funding_pubkey;
+               self.their_revocation_basepoint = msg.revocation_basepoint;
+               self.their_payment_basepoint = msg.payment_basepoint;
+               self.their_delayed_payment_basepoint = msg.delayed_payment_basepoint;
+               self.their_htlc_basepoint = msg.htlc_basepoint;
+               self.their_cur_commitment_point = msg.first_per_commitment_point;
+
+               let obscure_factor = self.get_commitment_transaction_number_obscure_factor();
+               self.channel_monitor.set_commitment_obscure_factor(obscure_factor);
+
+               self.channel_state = ChannelState::OurInitSent as u32 | ChannelState::TheirInitSent as u32;
+
+               Ok(())
+       }
+
+       fn funding_created_signature(&mut self, sig: &Signature) -> Result<(Transaction, Signature), HandleError> {
+               let funding_script = self.get_funding_redeemscript();
+
+               let remote_keys = try!(self.build_remote_transaction_keys());
+               let remote_initial_commitment_tx = try!(self.build_commitment_transaction(self.cur_remote_commitment_transaction_number, &remote_keys, false, false)).0;
+               let remote_sighash = secp_call!(Message::from_slice(&bip143::SighashComponents::new(&remote_initial_commitment_tx).sighash_all(&remote_initial_commitment_tx, 0, &funding_script, self.channel_value_satoshis)[..]));
+
+               let local_keys = try!(self.build_local_transaction_keys(self.cur_local_commitment_transaction_number));
+               let local_initial_commitment_tx = try!(self.build_commitment_transaction(self.cur_local_commitment_transaction_number, &local_keys, true, false)).0;
+               let local_sighash = secp_call!(Message::from_slice(&bip143::SighashComponents::new(&local_initial_commitment_tx).sighash_all(&local_initial_commitment_tx, 0, &funding_script, self.channel_value_satoshis)[..]));
+
+               // They sign the "local" commitment transaction, allowing us to broadcast the tx if we wish.
+               secp_call!(self.secp_ctx.verify(&local_sighash, &sig, &self.their_funding_pubkey));
+
+               // We sign the "remote" commitment transaction, allowing them to broadcast the tx if they wish.
+               Ok((remote_initial_commitment_tx, secp_call!(self.secp_ctx.sign(&remote_sighash, &self.local_keys.funding_key))))
+       }
+
+       pub fn funding_created(&mut self, msg: &msgs::FundingCreated) -> Result<msgs::FundingSigned, HandleError> {
+               if self.channel_outbound {
+                       return Err(HandleError{err: "Received funding_created for an outbound channel?", msg: None});
+               }
+               if self.channel_state != (ChannelState::OurInitSent as u32 | ChannelState::TheirInitSent as u32) {
+                       return Err(HandleError{err: "Received funding_created after we got the channel!", msg: None});
+               }
+               if self.channel_monitor.get_min_seen_secret() != (1 << 48) || self.cur_remote_commitment_transaction_number != (1 << 48) - 1 || self.cur_local_commitment_transaction_number != (1 << 48) - 1 {
+                       panic!("Should not have advanced channel commitment tx numbers prior to funding_created");
+               }
+
+               self.channel_monitor.set_funding_info(msg.funding_txid, msg.funding_output_index);
+
+               let (remote_initial_commitment_tx, our_signature) = match self.funding_created_signature(&msg.signature) {
+                       Ok((remote_initial_commitment_tx, sig)) => (remote_initial_commitment_tx, sig),
+                       Err(e) => {
+                               self.channel_monitor.unset_funding_info();
+                               return Err(e);
+                       }
+               };
+
+               // Now that we're past error-generating stuff, update our local state:
+
+               //TODO: Determine which tx index in remote_initial_commitment_transaction's outputs
+               //represent a revokeable script!
+               self.channel_monitor.provide_tx_info(&remote_initial_commitment_tx, 0, Vec::new());
+               self.channel_state = ChannelState::FundingSent as u32;
+               let funding_txo = self.channel_monitor.get_funding_txo().unwrap();
+               self.channel_id = funding_txo.0.into_be() ^ Uint256::from_u64(funding_txo.1 as u64).unwrap(); //TODO: or le?
+
+               Ok(msgs::FundingSigned {
+                       channel_id: self.channel_id,
+                       signature: our_signature
+               })
+       }
+
+       /// Handles a funding_signed message from the remote end.
+       /// If this call is successfull, broadcast the funding transaction (and not before!)
+       pub fn funding_signed(&mut self, msg: &msgs::FundingSigned) -> Result<(), HandleError> {
+               if !self.channel_outbound {
+                       return Err(HandleError{err: "Received funding_signed for an inbound channel?", msg: None});
+               }
+               if self.channel_state != ChannelState::FundingCreated as u32 {
+                       return Err(HandleError{err: "Received funding_signed in strange state!", msg: None});
+               }
+               if self.channel_monitor.get_min_seen_secret() != (1 << 48) || self.cur_remote_commitment_transaction_number != (1 << 48) - 1 || self.cur_local_commitment_transaction_number != (1 << 48) - 1 {
+                       panic!("Should not have advanced channel commitment tx numbers prior to funding_created");
+               }
+
+               let funding_script = self.get_funding_redeemscript();
+
+               let local_keys = try!(self.build_local_transaction_keys(self.cur_local_commitment_transaction_number));
+               let local_initial_commitment_tx = try!(self.build_commitment_transaction(self.cur_local_commitment_transaction_number, &local_keys, true, false)).0;
+               let local_sighash = secp_call!(Message::from_slice(&bip143::SighashComponents::new(&local_initial_commitment_tx).sighash_all(&local_initial_commitment_tx, 0, &funding_script, self.channel_value_satoshis)[..]));
+
+               // They sign the "local" commitment transaction, allowing us to broadcast the tx if we wish.
+               secp_call!(self.secp_ctx.verify(&local_sighash, &msg.signature, &self.their_funding_pubkey));
+
+               self.channel_state = ChannelState::FundingSent as u32;
+
+               Ok(())
+       }
+
+       pub fn funding_locked(&mut self, msg: &msgs::FundingLocked) -> Result<(), HandleError> {
+               if self.channel_state == ChannelState::FundingSent as u32 {
+                       self.channel_state |= ChannelState::TheirFundingLocked as u32;
+               } else if self.channel_state == (ChannelState::FundingSent as u32 | ChannelState::OurFundingLocked as u32) {
+                       self.channel_state = ChannelState::ChannelFunded as u32;
+               } else if self.channel_state < ChannelState::FundingSent as u32 {
+                       return Err(HandleError{err: "Peer sent a funding_locked before we'd even been told the funding txid", msg: None});
+               }
+
+               //TODO: Note that this must be a duplicate of the previous commitment point they sent us,
+               //as otherwise we will have a commitment transaction that they cant revoke (well, kinda,
+               //they can by sending two revoke_and_acks back-to-back, but not really). This appears to be
+               //a protocol oversight, but I assume I'm just missing something.
+               if self.their_cur_commitment_point != msg.next_per_commitment_point {
+                       return Err(HandleError{err: "Non-duplicate next_per_commitment_point in funding_locked", msg: None});
+               }
+               self.their_cur_commitment_point = msg.next_per_commitment_point;
+               Ok(())
+       }
+
+       /// Returns (inbound_htlc_count, outbound_htlc_count, htlc_outbound_value_msat, htlc_inbound_value_msat)
+       fn get_pending_htlc_stats(&self) -> (u32, u32, u64, u64) {
+               let mut inbound_htlc_count: u32 = 0;
+               let mut outbound_htlc_count: u32 = 0;
+               let mut htlc_outbound_value_msat = 0;
+               let mut htlc_inbound_value_msat = 0;
+               for ref htlc in self.pending_htlcs.iter() {
+                       if !htlc.outbound {
+                               inbound_htlc_count += 1;
+                               htlc_inbound_value_msat += htlc.amount_msat;
+                       } else {
+                               outbound_htlc_count += 1;
+                               htlc_outbound_value_msat += htlc.amount_msat;
+                       }
+               }
+               (inbound_htlc_count, outbound_htlc_count, htlc_outbound_value_msat, htlc_inbound_value_msat)
+       }
+
+       pub fn update_add_htlc(&mut self, msg: &msgs::UpdateAddHTLC, pending_forward_state: PendingForwardHTLCInfo) -> Result<(), HandleError> {
+               if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) {
+                       return Err(HandleError{err: "Got add HTLC message when channel was not in an operational state", msg: None});
+               }
+               if msg.amount_msat > self.channel_value_satoshis * 1000 {
+                       return Err(HandleError{err: "Remote side tried to send more than the total value of the channel", msg: None});
+               }
+               if msg.amount_msat < self.our_htlc_minimum_msat {
+                       return Err(HandleError{err: "Remote side tried to send less than our minimum HTLC value", msg: None});
+               }
+
+               let (inbound_htlc_count, _, htlc_outbound_value_msat, htlc_inbound_value_msat) = self.get_pending_htlc_stats();
+               if inbound_htlc_count + 1 > OUR_MAX_HTLCS as u32 {
+                       return Err(HandleError{err: "Remote tried to push more than our max accepted HTLCs", msg: None});
+               }
+               //TODO: Spec is unclear if this is per-direction or in total (I assume per direction):
+               // Check our_max_htlc_value_in_flight_msat
+               if htlc_inbound_value_msat + msg.amount_msat > Channel::get_our_max_htlc_value_in_flight_msat(self.channel_value_satoshis) {
+                       return Err(HandleError{err: "Remote HTLC add would put them over their max HTLC value in flight", msg: None});
+               }
+               // Check our_channel_reserve_satoshis:
+               if htlc_inbound_value_msat + htlc_outbound_value_msat + msg.amount_msat > (self.channel_value_satoshis - Channel::get_our_channel_reserve_satoshis(self.channel_value_satoshis)) * 1000 {
+                       return Err(HandleError{err: "Remote HTLC add would put them over their reserve value", msg: None});
+               }
+               if self.next_remote_htlc_id != msg.htlc_id {
+                       return Err(HandleError{err: "Remote skipped HTLC ID", msg: None});
+               }
+               if msg.cltv_expiry >= 500000000 {
+                       return Err(HandleError{err: "Remote provided CLTV expiry in seconds instead of block height", msg: None});
+               }
+
+               //TODO: Check msg.cltv_expiry further? Do this in channel manager?
+
+               // Now update local state:
+               self.next_remote_htlc_id += 1;
+               self.pending_htlcs.push(HTLCOutput {
+                       outbound: false,
+                       htlc_id: msg.htlc_id,
+                       amount_msat: msg.amount_msat,
+                       payment_hash: msg.payment_hash,
+                       cltv_expiry: msg.cltv_expiry,
+                       state: HTLCState::RemoteAnnounced,
+                       pending_forward_state: Some(pending_forward_state),
+               });
+
+               Ok(())
+       }
+
+       /// Removes an outbound HTLC which has been commitment_signed by the remote end
+       fn remove_htlc(&mut self, htlc_id: u64, check_preimage: Option<[u8; 32]>) -> Result<HTLCOutput, HandleError> {
+               let mut found_idx = None;
+               for (idx, ref htlc) in self.pending_htlcs.iter().enumerate() {
+                       if htlc.outbound && htlc.htlc_id == htlc_id {
+                               match check_preimage {
+                                       None => {},
+                                       Some(payment_hash) =>
+                                               if payment_hash != htlc.payment_hash {
+                                                       return Err(HandleError{err: "Remote tried to fulfill HTLC with an incorrect preimage", msg: None});
+                                               }
+                               };
+                               found_idx = Some(idx);
+                               break;
+                       }
+               }
+               match found_idx {
+                       None => Err(HandleError{err: "Remote tried to fulfill an HTLC we couldn't find", msg: None}),
+                       Some(idx) => {
+                               Ok(self.pending_htlcs.swap_remove(idx))
+                       }
+               }
+       }
+
+       /// Used to fulfill holding_cell_htlcs when we get a remote ack (or implicitly get it by them
+       /// fulfilling or failing the last pending HTLC)
+       fn free_holding_cell_htlcs(&mut self) -> Result<Option<(Vec<msgs::UpdateAddHTLC>, msgs::CommitmentSigned)>, HandleError> {
+               if self.holding_cell_htlcs.len() != 0 {
+                       let mut new_htlcs = self.holding_cell_htlcs.split_off(0);
+                       let mut update_add_msgs = Vec::with_capacity(new_htlcs.len());
+                       let mut err = None;
+                       for new_htlc in new_htlcs.drain(..) {
+                               // Note that this *can* fail, though it should be due to rather-rare conditions on
+                               // fee races with adding too many outputs which push our total payments just over
+                               // the limit. In case its less rare than I anticipate, we may want to revisit
+                               // handling this case better and maybe fufilling some of the HTLCs while attempting
+                               // to rebalance channels.
+                               if self.holding_cell_htlcs.len() != 0 {
+                                       self.holding_cell_htlcs.push(new_htlc);
+                               } else {
+                                       match self.send_htlc(new_htlc.amount_msat, new_htlc.payment_hash, new_htlc.cltv_expiry, new_htlc.onion_routing_packet.clone()) {
+                                               Ok(update_add_msg_option) => update_add_msgs.push(update_add_msg_option.unwrap()),
+                                               Err(e) => {
+                                                       self.holding_cell_htlcs.push(new_htlc);
+                                                       err = Some(e);
+                                               }
+                                       }
+                               }
+                       }
+                       //TODO: Need to examine the type of err - if its a fee issue or similar we may want to
+                       //fail it back the route, if its a temporary issue we can ignore it...
+                       if update_add_msgs.len() > 0 {
+                               Ok(Some((update_add_msgs, try!(self.send_commitment()))))
+                       } else {
+                               Err(err.unwrap())
+                       }
+               } else {
+                       Ok(None)
+               }
+       }
+
+       /// Checks if there are any LocalAnnounced HTLCs remaining and sets
+       /// ChannelState::AwaitingRemoteRevoke accordingly, possibly calling free_holding_cell_htlcs.
+       fn check_and_free_holding_cell_htlcs(&mut self) -> Result<Option<(Vec<msgs::UpdateAddHTLC>, msgs::CommitmentSigned)>, HandleError> {
+               if (self.channel_state & (ChannelState::AwaitingRemoteRevoke as u32)) == (ChannelState::AwaitingRemoteRevoke as u32) {
+                       for htlc in self.pending_htlcs.iter() {
+                               if htlc.state == HTLCState::LocalAnnounced {
+                                       return Ok(None);
+                               }
+                       }
+                       self.channel_state &= !(ChannelState::AwaitingRemoteRevoke as u32);
+                       self.free_holding_cell_htlcs()
+               } else {
+                       Ok(None)
+               }
+       }
+
+       pub fn update_fulfill_htlc(&mut self, msg: &msgs::UpdateFulfillHTLC) -> Result<Option<(Vec<msgs::UpdateAddHTLC>, msgs::CommitmentSigned)>, HandleError> {
+               if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) {
+                       return Err(HandleError{err: "Got add HTLC message when channel was not in an operational state", msg: None});
+               }
+
+               let mut sha = Sha256::new();
+               sha.input(&msg.payment_preimage);
+               let mut payment_hash = [0; 32];
+               sha.result(&mut payment_hash);
+
+               //TODO: Tell channel_monitor about the payment_preimage
+
+               match self.remove_htlc(msg.htlc_id, Some(payment_hash)) {
+                       Err(e) => return Err(e),
+                       Ok(htlc) => {
+                               //TODO: Double-check that we didn't exceed some limits (or value_to_self went
+                               //negative here?)
+                               self.value_to_self_msat -= htlc.amount_msat;
+                       }
+               }
+
+               self.check_and_free_holding_cell_htlcs()
+       }
+
+
+       pub fn update_fail_htlc(&mut self, msg: &msgs::UpdateFailHTLC) -> Result<Option<(Vec<msgs::UpdateAddHTLC>, msgs::CommitmentSigned)>, HandleError> {
+               if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) {
+                       return Err(HandleError{err: "Got add HTLC message when channel was not in an operational state", msg: None});
+               }
+
+               //TODO: Lots of checks here (and implementation after the remove?)
+
+               match self.remove_htlc(msg.htlc_id, None) {
+                       Err(e) => return Err(e),
+                       Ok(_htlc) => {
+                               //TODO: Double-check that we didn't exceed some limits (or value_to_self went
+                               //negative here?)
+                               ////TODO: Something?
+                       }
+               }
+
+               self.check_and_free_holding_cell_htlcs()
+       }
+
+       pub fn update_fail_malformed_htlc(&mut self, msg: &msgs::UpdateFailMalformedHTLC) -> Result<Option<(Vec<msgs::UpdateAddHTLC>, msgs::CommitmentSigned)>, HandleError> {
+               if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) {
+                       return Err(HandleError{err: "Got add HTLC message when channel was not in an operational state", msg: None});
+               }
+
+               //TODO: Lots of checks here (and implementation after the remove?)
+
+               match self.remove_htlc(msg.htlc_id, None) {
+                       Err(e) => return Err(e),
+                       Ok(_htlc) => {
+                               //TODO: Double-check that we didn't exceed some limits (or value_to_self went
+                               //negative here?)
+                               ////TODO: Something?
+                       }
+               }
+
+               self.check_and_free_holding_cell_htlcs()
+       }
+
+       pub fn commitment_signed(&mut self, msg: &msgs::CommitmentSigned) -> Result<(msgs::RevokeAndACK, Vec<PendingForwardHTLCInfo>), HandleError> {
+               if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) {
+                       return Err(HandleError{err: "Got commitment signed message when channel was not in an operational state", msg: None});
+               }
+
+               let funding_script = self.get_funding_redeemscript();
+
+               let local_keys = try!(self.build_local_transaction_keys(self.cur_local_commitment_transaction_number));
+               let local_commitment_tx = try!(self.build_commitment_transaction(self.cur_local_commitment_transaction_number, &local_keys, true, false));
+               let local_sighash = secp_call!(Message::from_slice(&bip143::SighashComponents::new(&local_commitment_tx.0).sighash_all(&local_commitment_tx.0, 0, &funding_script, self.channel_value_satoshis)[..]));
+               secp_call!(self.secp_ctx.verify(&local_sighash, &msg.signature, &self.their_funding_pubkey));
+
+               if msg.htlc_signatures.len() != local_commitment_tx.1.len() {
+                       return Err(HandleError{err: "Got wrong number of HTLC signatures from remote", msg: None});
+               }
+
+               for (idx, ref htlc) in local_commitment_tx.1.iter().enumerate() {
+                       let htlc_tx = try!(self.build_htlc_transaction(&local_commitment_tx.0.txid(), htlc, true, &local_keys));
+                       let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &local_keys, htlc.offered);
+                       let htlc_sighash = secp_call!(Message::from_slice(&bip143::SighashComponents::new(&htlc_tx).sighash_all(&htlc_tx, 0, &htlc_redeemscript, htlc.amount_msat / 1000)[..]));
+                       secp_call!(self.secp_ctx.verify(&htlc_sighash, &msg.htlc_signatures[idx], &local_keys.b_htlc_key));
+               }
+
+               let next_per_commitment_point = PublicKey::from_secret_key(&self.secp_ctx, &try!(self.build_local_commitment_secret(self.cur_local_commitment_transaction_number - 1))).unwrap();
+               let per_commitment_secret = chan_utils::build_commitment_secret(self.local_keys.commitment_seed, self.cur_local_commitment_transaction_number);
+
+               //TODO: Store htlc keys in our channel_watcher
+
+               // Update state now that we've passed all the can-fail calls...
+
+               let mut to_forward_infos = Vec::new();
+               for ref mut htlc in self.pending_htlcs.iter_mut() {
+                       if htlc.state == HTLCState::RemoteAnnounced {
+                               htlc.state = HTLCState::Committed;
+                               to_forward_infos.push(htlc.pending_forward_state.take().unwrap());
+                       }
+               }
+
+               self.cur_local_commitment_transaction_number -= 1;
+
+               Ok((msgs::RevokeAndACK {
+                       channel_id: self.channel_id,
+                       per_commitment_secret: per_commitment_secret,
+                       next_per_commitment_point: next_per_commitment_point,
+               }, to_forward_infos))
+       }
+
+       /// Handles receiving a remote's revoke_and_ack. Note that we may return a new
+       /// commitment_signed message here in case we had pending outbound HTLCs to add which were
+       /// waiting on this revoke_and_ack. The generation of this new commitment_signed may also fail,
+       /// generating an appropriate error *after* the channel state has been updated based on the
+       /// revoke_and_ack message.
+       pub fn revoke_and_ack(&mut self, msg: &msgs::RevokeAndACK) -> Result<Option<(Vec<msgs::UpdateAddHTLC>, msgs::CommitmentSigned)>, HandleError> {
+               if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) {
+                       return Err(HandleError{err: "Got revoke/ACK message when channel was not in an operational state", msg: None});
+               }
+               if PublicKey::from_secret_key(&self.secp_ctx, &get_key!(&self.secp_ctx, &msg.per_commitment_secret)).unwrap() != self.their_cur_commitment_point {
+                       return Err(HandleError{err: "Got a revoke commitment secret which didn't correspond to their current pubkey", msg: None});
+               }
+               try!(self.channel_monitor.provide_secret(self.cur_remote_commitment_transaction_number, msg.per_commitment_secret));
+
+               // Update state now that we've passed all the can-fail calls...
+               // (note that we may still fail to generate the new commitment_signed message, but that's
+               // OK, we step the channel here and *then* if the new generation fails we can fail the
+               // channel based on that, but stepping stuff here should be safe either way.
+               self.channel_state &= !(ChannelState::AwaitingRemoteRevoke as u32);
+               self.their_cur_commitment_point = msg.next_per_commitment_point;
+               self.cur_remote_commitment_transaction_number -= 1;
+               for htlc in self.pending_htlcs.iter_mut() {
+                       if htlc.state == HTLCState::LocalAnnounced {
+                               htlc.state = HTLCState::Committed;
+                       }
+               }
+
+               self.free_holding_cell_htlcs()
+       }
+
+       pub fn update_fee(&mut self, fee_estimator: &FeeEstimator, msg: &msgs::UpdateFee) -> Result<(), HandleError> {
+        if self.channel_outbound {
+                       return Err(HandleError{err: "Non-funding remote tried to update channel fee", msg: None});
+        }
+               Channel::check_remote_fee(fee_estimator, msg.feerate_per_kw).unwrap();
+               self.feerate_per_kw = msg.feerate_per_kw as u64;
+               Ok(())
+       }
+
+       // Public utilities:
+
+       pub fn channel_id(&self) -> Uint256 {
+               self.channel_id
+       }
+
+       /// Gets the "user_id" value passed into the construction of this channel. It has no special
+       /// meaning and exists only to allow users to have a persistent identifier of a channel.
+       pub fn get_user_id(&self) -> u64 {
+               self.user_id
+       }
+
+       /// Guaranteed to be Some after both FundingLocked messages have been exchanged (and, thus,
+       /// is_usable() returns true).
+       pub fn get_short_channel_id(&self) -> Option<u64> {
+               self.short_channel_id
+       }
+
+       /// Returns the funding_txo we either got from our peer, or were given by
+       /// get_outbound_funding_created.
+       pub fn get_funding_txo(&self) -> Option<(Sha256dHash, u16)> {
+               self.channel_monitor.get_funding_txo()
+       }
+
+       pub fn get_their_node_id(&self) -> PublicKey {
+               self.their_node_id
+       }
+
+       pub fn get_our_htlc_minimum_msat(&self) -> u64 {
+               self.our_htlc_minimum_msat
+       }
+
+       pub fn get_value_satoshis(&self) -> u64 {
+               self.channel_value_satoshis
+       }
+
+       pub fn get_channel_update_count(&mut self) -> u32 {
+               self.channel_update_count += 1; //TODO: This should be base on updates, not updates *sent*
+               self.channel_update_count
+       }
+
+       /// Gets the fee we'd want to charge for adding an HTLC output to this Channel
+       pub fn get_our_fee_base_msat(&self, fee_estimator: &FeeEstimator) -> u32 {
+               // For lack of a better metric, we calculate what it would cost to consolidate the new HTLC
+               // output value back into a transaction with the regular channel output:
+
+               // the fee cost of the HTLC-Success/HTLC-Timeout transaction:
+               let mut res = self.feerate_per_kw * cmp::max(HTLC_TIMEOUT_TX_WEIGHT, HTLC_SUCCESS_TX_WEIGHT);
+
+               if self.channel_outbound {
+                       // + the marginal fee increase cost to us in the commitment transaction:
+                       res += self.feerate_per_kw * COMMITMENT_TX_WEIGHT_PER_HTLC;
+               }
+
+               // + the marginal cost of an input which spends the HTLC-Success/HTLC-Timeout output:
+               res += fee_estimator.get_est_sat_per_vbyte(ConfirmationTarget::Normal) * SPENDING_INPUT_FOR_A_OUTPUT_WEIGHT * 250;
+
+               res as u32
+       }
+
+       pub fn channel_monitor(&self) -> ChannelMonitor {
+               if self.channel_state < ChannelState::FundingCreated as u32 {
+                       panic!("Can't get a channel monitor until funding has been created");
+               }
+               self.channel_monitor.clone()
+       }
+
+       /// Returns true if this channel is fully established and not known to be closing.
+       pub fn is_usable(&self) -> bool {
+               (self.channel_state & (ChannelState::ChannelFunded as u32)) == (ChannelState::ChannelFunded as u32)
+       }
+
+       /// Returns true if this channel is currently available for use. This is a superset of
+       /// is_usable() and considers things like the channel being temporarily disabled.
+       pub fn is_live(&self) -> bool {
+               self.is_usable()
+       }
+
+       /// Called by channelmanager based on chain blocks being connected.
+       /// Note that we only need to use this to detect funding_signed, anything else is handled by
+       /// the channel_monitor.
+       pub fn block_connected(&mut self, header: &BlockHeader, height: u32, txn_matched: &[&Transaction], indexes_of_txn_matched: &[u32]) -> Option<msgs::FundingLocked> {
+               if self.funding_tx_confirmations > 0 {
+                       if header.bitcoin_hash() != self.last_block_connected {
+                               self.last_block_connected = header.bitcoin_hash();
+                               self.funding_tx_confirmations += 1;
+                               if self.funding_tx_confirmations == CONF_TARGET as u64 {
+                                       if self.channel_state == ChannelState::FundingSent as u32 {
+                                               self.channel_state |= ChannelState::OurFundingLocked as u32;
+                                       } else if self.channel_state == (ChannelState::FundingSent as u32 | ChannelState::TheirFundingLocked as u32) {
+                                               self.channel_state = ChannelState::ChannelFunded as u32;
+                                               //TODO: Something about a state where we "lost confirmation"
+                                       } else if self.channel_state < ChannelState::ChannelFunded as u32 {
+                                               panic!("Started confirming a channel in a state pre-FundingSent?");
+                                       }
+                                       self.funding_tx_confirmed_in = header.bitcoin_hash();
+
+                                       //TODO: Note that this must be a duplicate of the previous commitment point they sent us,
+                                       //as otherwise we will have a commitment transaction that they cant revoke (well, kinda,
+                                       //they can by sending two revoke_and_acks back-to-back, but not really). This appears to be
+                                       //a protocol oversight, but I assume I'm just missing something.
+                                       let next_per_commitment_secret = match self.build_local_commitment_secret(self.cur_local_commitment_transaction_number) {
+                                               Ok(secret) => secret,
+                                               Err(_) => return None
+                                       };
+
+                                       let next_per_commitment_point = PublicKey::from_secret_key(&self.secp_ctx, &next_per_commitment_secret).unwrap();
+                                       return Some(msgs::FundingLocked {
+                                               channel_id: self.channel_id,
+                                               next_per_commitment_point: next_per_commitment_point,
+                                       });
+                               }
+                       }
+               }
+               if self.channel_state & !(ChannelState::TheirFundingLocked as u32) == ChannelState::FundingSent as u32 {
+                       for (ref tx, index_in_block) in txn_matched.iter().zip(indexes_of_txn_matched) {
+                               if tx.txid() == self.channel_monitor.get_funding_txo().unwrap().0 {
+                                       self.funding_tx_confirmations = 1;
+                                       self.short_channel_id = Some(((height as u64)          << (5*8)) |
+                                                                    ((*index_in_block as u64) << (2*8)) |
+                                                                    ((self.channel_monitor.get_funding_txo().unwrap().1 as u64) << (2*8)));
+                               }
+                       }
+               }
+               None
+       }
+
+       /// Called by channelmanager based on chain blocks being disconnected.
+       /// Returns true if we need to close the channel now due to funding transaction
+       /// unconfirmation/reorg.
+       pub fn block_disconnected(&mut self, header: &BlockHeader) -> bool {
+               if self.funding_tx_confirmations > 0 {
+                       self.funding_tx_confirmations -= 1;
+                       if self.funding_tx_confirmations == UNCONF_THRESHOLD as u64 {
+                               return true;
+                       }
+               }
+               if header.bitcoin_hash() == self.funding_tx_confirmed_in {
+                       self.funding_tx_confirmations = CONF_TARGET as u64 - 1;
+               }
+               false
+       }
+
+       // Methods to get unprompted messages to send to the remote end (or where we already returned
+       // something in the handler for the message that prompted this message):
+
+       pub fn get_open_channel(&self, chain_hash: Sha256dHash, fee_estimator: &FeeEstimator) -> Result<msgs::OpenChannel, HandleError> {
+               if !self.channel_outbound {
+                       panic!("Tried to open a channel for an inbound channel?");
+               }
+               if self.channel_state != ChannelState::OurInitSent as u32 {
+                       return Err(HandleError{err: "Cannot generate an open_channel after we've moved forward", msg: None});
+               }
+
+               if self.cur_local_commitment_transaction_number != (1 << 48) - 1 {
+                       panic!("Tried to send an open_channel for a channel that has already advanced");
+               }
+
+               let local_commitment_secret = try!(self.build_local_commitment_secret(self.cur_local_commitment_transaction_number));
+
+               Ok(msgs::OpenChannel {
+                       chain_hash: chain_hash,
+                       temporary_channel_id: self.channel_id,
+                       funding_satoshis: self.channel_value_satoshis,
+                       push_msat: 0, //TODO: Something about feerate?
+                       dust_limit_satoshis: self.our_dust_limit_satoshis,
+                       max_htlc_value_in_flight_msat: Channel::get_our_max_htlc_value_in_flight_msat(self.channel_value_satoshis),
+                       channel_reserve_satoshis: Channel::get_our_channel_reserve_satoshis(self.channel_value_satoshis),
+                       htlc_minimum_msat: self.our_htlc_minimum_msat,
+                       feerate_per_kw: fee_estimator.get_est_sat_per_vbyte(ConfirmationTarget::Background) as u32 * 250,
+                       to_self_delay: BREAKDOWN_TIMEOUT,
+                       max_accepted_htlcs: OUR_MAX_HTLCS,
+                       funding_pubkey: PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.funding_key).unwrap(),
+                       revocation_basepoint: PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.revocation_base_key).unwrap(),
+                       payment_basepoint: PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.payment_base_key).unwrap(),
+                       delayed_payment_basepoint: PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.delayed_payment_base_key).unwrap(),
+                       htlc_basepoint: PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.htlc_base_key).unwrap(),
+                       first_per_commitment_point: PublicKey::from_secret_key(&self.secp_ctx, &local_commitment_secret).unwrap(),
+                       channel_flags: if self.announce_publicly {1} else {0},
+                       shutdown_scriptpubkey: None,
+               })
+       }
+
+       pub fn get_accept_channel(&self) -> Result<msgs::AcceptChannel, HandleError> {
+               if self.channel_outbound {
+                       panic!("Tried to send accept_channel for an outbound channel?");
+               }
+               if self.channel_state != (ChannelState::OurInitSent as u32) | (ChannelState::TheirInitSent as u32) {
+                       panic!("Tried to send accept_channel after channel had moved forward");
+               }
+               if self.cur_local_commitment_transaction_number != (1 << 48) - 1 {
+                       panic!("Tried to send an accept_channel for a channel that has already advanced");
+               }
+
+               let local_commitment_secret = try!(self.build_local_commitment_secret(self.cur_local_commitment_transaction_number));
+
+               Ok(msgs::AcceptChannel {
+                       temporary_channel_id: self.channel_id,
+                       dust_limit_satoshis: self.our_dust_limit_satoshis,
+                       max_htlc_value_in_flight_msat: Channel::get_our_max_htlc_value_in_flight_msat(self.channel_value_satoshis),
+                       channel_reserve_satoshis: Channel::get_our_channel_reserve_satoshis(self.channel_value_satoshis),
+                       htlc_minimum_msat: self.our_htlc_minimum_msat,
+                       minimum_depth: CONF_TARGET,
+                       to_self_delay: BREAKDOWN_TIMEOUT,
+                       max_accepted_htlcs: OUR_MAX_HTLCS,
+                       funding_pubkey: PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.funding_key).unwrap(),
+                       revocation_basepoint: PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.revocation_base_key).unwrap(),
+                       payment_basepoint: PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.payment_base_key).unwrap(),
+                       delayed_payment_basepoint: PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.delayed_payment_base_key).unwrap(),
+                       htlc_basepoint: PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.htlc_base_key).unwrap(),
+                       first_per_commitment_point: PublicKey::from_secret_key(&self.secp_ctx, &local_commitment_secret).unwrap(),
+                       shutdown_scriptpubkey: None,
+               })
+       }
+
+       fn get_outbound_funding_created_signature(&mut self) -> Result<Signature, HandleError> {
+               let funding_script = self.get_funding_redeemscript();
+
+               let remote_keys = try!(self.build_remote_transaction_keys());
+               let remote_initial_commitment_tx = try!(self.build_commitment_transaction(self.cur_remote_commitment_transaction_number, &remote_keys, false, false)).0;
+               let remote_sighash = secp_call!(Message::from_slice(&bip143::SighashComponents::new(&remote_initial_commitment_tx).sighash_all(&remote_initial_commitment_tx, 0, &funding_script, self.channel_value_satoshis)[..]));
+
+               // We sign the "remote" commitment transaction, allowing them to broadcast the tx if they wish.
+               Ok(secp_call!(self.secp_ctx.sign(&remote_sighash, &self.local_keys.funding_key)))
+       }
+
+       /// Updates channel state with knowledge of the funding transaction's txid/index, and generates
+       /// a funding_created message for the remote peer.
+       /// Panics if called at some time other than immediately after initial handshake, if called twice,
+       /// or if called on an inbound channel.
+       /// Note that channel_id changes during this call!
+       /// Do NOT broadcast the funding transaction until after a successfull funding_signed call!
+       pub fn get_outbound_funding_created(&mut self, funding_txid: Sha256dHash, funding_output_index: u16) -> Result<msgs::FundingCreated, HandleError> {
+               if !self.channel_outbound {
+                       panic!("Tried to create outbound funding_created message on an inbound channel!");
+               }
+               if self.channel_state != (ChannelState::OurInitSent as u32 | ChannelState::TheirInitSent as u32) {
+                       panic!("Tried to get a funding_created messsage at a time other than immediately after initial handshake completion (or tried to get funding_created twice)");
+               }
+               if self.channel_monitor.get_min_seen_secret() != (1 << 48) || self.cur_remote_commitment_transaction_number != (1 << 48) - 1 || self.cur_local_commitment_transaction_number != (1 << 48) - 1 {
+                       panic!("Should not have advanced channel commitment tx numbers prior to funding_created");
+               }
+
+               self.channel_monitor.set_funding_info(funding_txid, funding_output_index);
+
+               let our_signature = match self.get_outbound_funding_created_signature() {
+                       Ok(sig) => sig,
+                       Err(e) => {
+                               self.channel_monitor.unset_funding_info();
+                               return Err(e);
+                       }
+               };
+
+               let temporary_channel_id = self.channel_id;
+
+               // Now that we're past error-generating stuff, update our local state:
+
+               self.channel_state = ChannelState::FundingCreated as u32;
+               let funding_txo = self.channel_monitor.get_funding_txo().unwrap();
+               self.channel_id = funding_txo.0.into_be() ^ Uint256::from_u64(funding_txo.1 as u64).unwrap(); //TODO: or le?
+
+               Ok(msgs::FundingCreated {
+                       temporary_channel_id: temporary_channel_id,
+                       funding_txid: funding_txid,
+                       funding_output_index: funding_output_index,
+                       signature: our_signature
+               })
+       }
+
+       /// Gets an UnsignedChannelAnnouncement, as well as a signature covering it using our
+       /// bitcoin_key, if available, for this channel. The channel must be publicly announceable and
+       /// available for use (have exchanged FundingLocked messages in both directions. Should be used
+       /// for both loose and in response to an AnnouncementSignatures message from the remote peer.
+       pub fn get_channel_announcement(&self, our_node_id: PublicKey, chain_hash: Sha256dHash) -> Result<(msgs::UnsignedChannelAnnouncement, Signature), HandleError> {
+               if !self.announce_publicly {
+                       return Err(HandleError{err: "Channel is not available for public announcements", msg: None});
+               }
+               if self.channel_state < ChannelState::ChannelFunded as u32 {
+                       return Err(HandleError{err: "Cannot get a ChannelAnnouncement until the channel funding has been locked", msg: None});
+               }
+
+               let were_node_one = our_node_id.serialize()[..] < self.their_node_id.serialize()[..];
+               let our_bitcoin_key = PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.funding_key).unwrap();
+
+               let msg = msgs::UnsignedChannelAnnouncement {
+                       features: msgs::GlobalFeatures::new(),
+                       chain_hash: chain_hash,
+                       short_channel_id: self.get_short_channel_id().unwrap(),
+                       node_id_1: if were_node_one { our_node_id } else { self.get_their_node_id() },
+                       node_id_2: if were_node_one { self.get_their_node_id() } else { our_node_id },
+                       bitcoin_key_1: if were_node_one { our_bitcoin_key } else { self.their_funding_pubkey },
+                       bitcoin_key_2: if were_node_one { self.their_funding_pubkey } else { our_bitcoin_key },
+               };
+
+               let msghash = Message::from_slice(&Sha256dHash::from_data(&msg.encode()[..])[..]).unwrap();
+               let sig = secp_call!(self.secp_ctx.sign(&msghash, &self.local_keys.funding_key));
+
+               Ok((msg, sig))
+       }
+
+
+       // Send stuff to our remote peers:
+
+       /// Adds a pending outbound HTLC to this channel, note that you probably want
+       /// send_htlc_and_commit instead cause you'll want both messages at once.
+       /// This returns an option instead of a pure UpdateAddHTLC as we may be in a state where we are
+       /// waiting on the remote peer to send us a revoke_and_ack during which time we cannot add new
+       /// HTLCs on the wire or we wouldn't be able to determine what they actually ACK'ed.
+       pub fn send_htlc(&mut self, amount_msat: u64, payment_hash: [u8; 32], cltv_expiry: u32, onion_routing_packet: msgs::OnionPacket) -> Result<Option<msgs::UpdateAddHTLC>, HandleError> {
+               if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) {
+                       return Err(HandleError{err: "Cannot send HTLC until channel is fully established", msg: None});
+               }
+
+               if amount_msat > self.channel_value_satoshis * 1000 {
+                       return Err(HandleError{err: "Cannot send more than the total value of the channel", msg: None});
+               }
+               if amount_msat < self.their_htlc_minimum_msat {
+                       return Err(HandleError{err: "Cannot send less than their minimum HTLC value", msg: None});
+               }
+
+               let (_, outbound_htlc_count, htlc_outbound_value_msat, htlc_inbound_value_msat) = self.get_pending_htlc_stats();
+               if outbound_htlc_count + 1 > self.their_max_accepted_htlcs as u32 {
+                       return Err(HandleError{err: "Cannot push more than their max accepted HTLCs", msg: None});
+               }
+               //TODO: Spec is unclear if this is per-direction or in total (I assume per direction):
+               // Check their_max_htlc_value_in_flight_msat
+               if htlc_outbound_value_msat + amount_msat > self.their_max_htlc_value_in_flight_msat {
+                       return Err(HandleError{err: "Cannot send value that would put us over our max HTLC value in flight", msg: None});
+               }
+               // Check their_channel_reserve_satoshis:
+               if htlc_outbound_value_msat + amount_msat > (self.channel_value_satoshis - self.their_channel_reserve_satoshis) * 1000 - htlc_inbound_value_msat {
+                       return Err(HandleError{err: "Cannot send value that would put us over our reserve value", msg: None});
+               }
+
+               //TODO: Check cltv_expiry? Do this in channel manager?
+
+               // Now update local state:
+               if (self.channel_state & (ChannelState::AwaitingRemoteRevoke as u32)) == (ChannelState::AwaitingRemoteRevoke as u32) {
+                       //TODO: Check the limits *including* other pending holding cell HTLCs!
+                       self.holding_cell_htlcs.push(HTLCOutputAwaitingACK {
+                               amount_msat: amount_msat,
+                               payment_hash: payment_hash,
+                               cltv_expiry: cltv_expiry,
+                               onion_routing_packet: onion_routing_packet,
+                               time_created: Instant::now(),
+                       });
+                       return Ok(None);
+               }
+
+               self.pending_htlcs.push(HTLCOutput {
+                       outbound: true,
+                       htlc_id: self.next_local_htlc_id,
+                       amount_msat: amount_msat,
+                       payment_hash: payment_hash.clone(),
+                       cltv_expiry: cltv_expiry,
+                       state: HTLCState::LocalAnnounced,
+                       pending_forward_state: None
+               });
+
+               let res = msgs::UpdateAddHTLC {
+                       channel_id: self.channel_id,
+                       htlc_id: self.next_local_htlc_id,
+                       amount_msat: amount_msat,
+                       payment_hash: payment_hash,
+                       cltv_expiry: cltv_expiry,
+                       onion_routing_packet: onion_routing_packet,
+               };
+               self.next_local_htlc_id += 1;
+
+               Ok(Some(res))
+       }
+
+       /// Creates a signed commitment transaction to send to the remote peer.
+       pub fn send_commitment(&mut self) -> Result<msgs::CommitmentSigned, HandleError> {
+               if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) {
+                       return Err(HandleError{err: "Cannot create commitment tx until channel is fully established", msg: None});
+               }
+
+               let funding_script = self.get_funding_redeemscript();
+
+               let remote_keys = try!(self.build_remote_transaction_keys());
+               let remote_commitment_tx = try!(self.build_commitment_transaction(self.cur_remote_commitment_transaction_number, &remote_keys, false, true));
+               let remote_sighash = secp_call!(Message::from_slice(&bip143::SighashComponents::new(&remote_commitment_tx.0).sighash_all(&remote_commitment_tx.0, 0, &funding_script, self.channel_value_satoshis)[..]));
+               let our_sig = secp_call!(self.secp_ctx.sign(&remote_sighash, &self.local_keys.funding_key));
+
+               let mut htlc_sigs = Vec::new();
+
+               for ref htlc in remote_commitment_tx.1.iter() {
+                       let htlc_tx = try!(self.build_htlc_transaction(&remote_commitment_tx.0.txid(), htlc, false, &remote_keys));
+                       let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &remote_keys, htlc.offered);
+                       let htlc_sighash = secp_call!(Message::from_slice(&bip143::SighashComponents::new(&htlc_tx).sighash_all(&htlc_tx, 0, &htlc_redeemscript, htlc.amount_msat / 1000)[..]));
+                       let our_htlc_key = secp_call!(chan_utils::derive_private_key(&self.secp_ctx, &remote_keys.per_commitment_point, &self.local_keys.htlc_base_key));
+                       htlc_sigs.push(secp_call!(self.secp_ctx.sign(&htlc_sighash, &our_htlc_key)));
+               }
+
+               // Update state now that we've passed all the can-fail calls...
+               self.channel_state |= ChannelState::AwaitingRemoteRevoke as u32;
+
+               Ok(msgs::CommitmentSigned {
+                       channel_id: self.channel_id,
+                       signature: our_sig,
+                       htlc_signatures: htlc_sigs,
+               })
+       }
+
+       /// Adds a pending outbound HTLC to this channel, and creates a signed commitment transaction
+       /// to send to the remote peer in one go.
+       /// Shorthand for calling send_htlc() followed by send_commitment(), see docs on those for
+       /// more info.
+       pub fn send_htlc_and_commit(&mut self, amount_msat: u64, payment_hash: [u8; 32], cltv_expiry: u32, onion_routing_packet: msgs::OnionPacket) -> Result<Option<(msgs::UpdateAddHTLC, msgs::CommitmentSigned)>, HandleError> {
+               match try!(self.send_htlc(amount_msat, payment_hash, cltv_expiry, onion_routing_packet)) {
+                       Some(update_add_htlc) =>
+                               Ok(Some((update_add_htlc, try!(self.send_commitment())))),
+                       None => Ok(None)
+               }
+       }
+}
+
+#[cfg(test)]
+mod tests {
+       use bitcoin::util::misc::hex_bytes;
+       use bitcoin::util::hash::Sha256dHash;
+       use bitcoin::util::bip143;
+       use bitcoin::network::serialize::serialize;
+       use bitcoin::blockdata::transaction::Transaction;
+       use ln::channel::{Channel,HTLCOutput,HTLCState,HTLCOutputInCommitment,TxCreationKeys};
+       use ln::chan_utils;
+       use chain::chaininterface::{FeeEstimator,ConfirmationTarget};
+       use secp256k1::{Secp256k1,Message,Signature};
+       use secp256k1::key::{SecretKey,PublicKey};
+       use crypto::sha2::Sha256;
+       use crypto::digest::Digest;
+
+       struct TestFeeEstimator {
+               fee_est: u64
+       }
+       impl FeeEstimator for TestFeeEstimator {
+               fn get_est_sat_per_vbyte(&self, _: ConfirmationTarget) -> u64 {
+                       self.fee_est
+               }
+       }
+
+       #[test]
+       fn outbound_commitment_test() {
+               // Test vectors from BOLT 3 Appendix C:
+               let feeest = TestFeeEstimator{fee_est: 15000/250};
+               let mut chan = Channel::new_outbound(&feeest, PublicKey::new(), 10000000, false, 42); // Nothing uses their network key in this test
+               chan.their_to_self_delay = 144;
+               chan.our_dust_limit_satoshis = 546;
+
+               let secp_ctx = Secp256k1::new();
+
+               chan.local_keys.funding_key = SecretKey::from_slice(&secp_ctx, &hex_bytes("30ff4956bbdd3222d44cc5e8a1261dab1e07957bdac5ae88fe3261ef321f3749").unwrap()[..]).unwrap();
+               assert_eq!(PublicKey::from_secret_key(&secp_ctx, &chan.local_keys.funding_key).unwrap().serialize()[..],
+                               hex_bytes("023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb").unwrap()[..]);
+
+               chan.local_keys.payment_base_key = SecretKey::from_slice(&secp_ctx, &hex_bytes("1111111111111111111111111111111111111111111111111111111111111111").unwrap()[..]).unwrap();
+               chan.local_keys.delayed_payment_base_key = SecretKey::from_slice(&secp_ctx, &hex_bytes("3333333333333333333333333333333333333333333333333333333333333333").unwrap()[..]).unwrap();
+               chan.local_keys.htlc_base_key = SecretKey::from_slice(&secp_ctx, &hex_bytes("1111111111111111111111111111111111111111111111111111111111111111").unwrap()[..]).unwrap();
+               // chan.local_keys.commitment_seed isnt derived in the test vectors :(
+
+               chan.channel_monitor.set_funding_info(Sha256dHash::from_hex("8984484a580b825b9972d7adb15050b3ab624ccd731946b3eeddb92f4e7ef6be").unwrap(), 0);
+
+               chan.their_payment_basepoint = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex_bytes("4444444444444444444444444444444444444444444444444444444444444444").unwrap()[..]).unwrap()).unwrap();
+               assert_eq!(chan.their_payment_basepoint.serialize()[..],
+                               hex_bytes("032c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e668680991").unwrap()[..]);
+
+               chan.their_funding_pubkey = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex_bytes("1552dfba4f6cf29a62a0af13c8d6981d36d0ef8d61ba10fb0fe90da7634d7e13").unwrap()[..]).unwrap()).unwrap();
+               assert_eq!(chan.their_funding_pubkey.serialize()[..],
+                               hex_bytes("030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c1").unwrap()[..]);
+
+               chan.their_htlc_basepoint = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex_bytes("4444444444444444444444444444444444444444444444444444444444444444").unwrap()[..]).unwrap()).unwrap();
+               assert_eq!(chan.their_htlc_basepoint.serialize()[..],
+                               hex_bytes("032c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e668680991").unwrap()[..]);
+
+               chan.their_revocation_basepoint = PublicKey::from_slice(&secp_ctx, &hex_bytes("02466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f27").unwrap()[..]).unwrap();
+
+               // We can't just use build_local_transaction_keys here as the per_commitment_secret is not
+               // derived from a commitment_seed, so instead we copy it here and call
+               // build_commitment_transaction.
+               let delayed_payment_base = PublicKey::from_secret_key(&secp_ctx, &chan.local_keys.delayed_payment_base_key).unwrap();
+               let per_commitment_secret = SecretKey::from_slice(&secp_ctx, &hex_bytes("1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100").unwrap()[..]).unwrap();
+               let per_commitment_point = PublicKey::from_secret_key(&secp_ctx, &per_commitment_secret).unwrap();
+               let htlc_basepoint = PublicKey::from_secret_key(&secp_ctx, &chan.local_keys.htlc_base_key).unwrap();
+               let keys = TxCreationKeys::new(&secp_ctx, &per_commitment_point, &delayed_payment_base, &htlc_basepoint, &chan.their_revocation_basepoint, &chan.their_payment_basepoint, &chan.their_htlc_basepoint).unwrap();
+
+               let mut unsigned_tx: (Transaction, Vec<HTLCOutputInCommitment>);
+
+               macro_rules! test_commitment {
+                       ( $their_sig_hex: expr, $our_sig_hex: expr, $tx_hex: expr) => {
+                               unsigned_tx = chan.build_commitment_transaction(42, &keys, true, false).unwrap();
+                               let their_signature = Signature::from_der(&secp_ctx, &hex_bytes($their_sig_hex).unwrap()[..]).unwrap();
+                               let sighash = Message::from_slice(&bip143::SighashComponents::new(&unsigned_tx.0).sighash_all(&unsigned_tx.0, 0, &chan.get_funding_redeemscript(), chan.channel_value_satoshis)[..]).unwrap();
+                               secp_ctx.verify(&sighash, &their_signature, &chan.their_funding_pubkey).unwrap();
+
+                               chan.sign_commitment_transaction(&mut unsigned_tx.0, &their_signature).unwrap();
+
+                               assert_eq!(serialize(&unsigned_tx.0).unwrap()[..],
+                                               hex_bytes($tx_hex).unwrap()[..]);
+                       };
+               }
+
+               macro_rules! test_htlc_output {
+                       ( $htlc_idx: expr, $their_sig_hex: expr, $our_sig_hex: expr, $tx_hex: expr ) => {
+                               let remote_signature = Signature::from_der(&secp_ctx, &hex_bytes($their_sig_hex).unwrap()[..]).unwrap();
+
+                               let ref htlc = unsigned_tx.1[$htlc_idx];
+                               let mut htlc_tx = chan.build_htlc_transaction(&unsigned_tx.0.txid(), &htlc, true, &keys).unwrap();
+                               let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &keys, htlc.offered);
+                               let htlc_sighash = Message::from_slice(&bip143::SighashComponents::new(&htlc_tx).sighash_all(&htlc_tx, 0, &htlc_redeemscript, htlc.amount_msat / 1000)[..]).unwrap();
+                               secp_ctx.verify(&htlc_sighash, &remote_signature, &keys.b_htlc_key).unwrap();
+
+                               let mut preimage: Option<[u8; 32]> = None;
+                               if !htlc.offered {
+                                       for i in 0..5 {
+                                               let mut sha = Sha256::new();
+                                               sha.input(&[i; 32]);
+
+                                               let mut out = [0; 32];
+                                               sha.result(&mut out);
+
+                                               if out == htlc.payment_hash {
+                                                       preimage = Some([i; 32]);
+                                               }
+                                       }
+
+                                       assert!(preimage.is_some());
+                               }
+
+                               chan.sign_htlc_transaction(&mut htlc_tx, &remote_signature, &preimage, &htlc, &keys).unwrap();
+                               assert_eq!(serialize(&htlc_tx).unwrap()[..],
+                                               hex_bytes($tx_hex).unwrap()[..]);
+                       };
+               }
+
+               {
+                       // simple commitment tx with no HTLCs
+                       chan.value_to_self_msat = 7000000000;
+
+                       test_commitment!("3045022100f51d2e566a70ba740fc5d8c0f07b9b93d2ed741c3c0860c613173de7d39e7968022041376d520e9c0e1ad52248ddf4b22e12be8763007df977253ef45a4ca3bdb7c0",
+                                        "3044022051b75c73198c6deee1a875871c3961832909acd297c6b908d59e3319e5185a46022055c419379c5051a78d00dbbce11b5b664a0c22815fbcc6fcef6b1937c3836939",
+                                        "02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b8002c0c62d0000000000160014ccf1af2f2aabee14bb40fa3851ab2301de84311054a56a00000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0400473044022051b75c73198c6deee1a875871c3961832909acd297c6b908d59e3319e5185a46022055c419379c5051a78d00dbbce11b5b664a0c22815fbcc6fcef6b1937c383693901483045022100f51d2e566a70ba740fc5d8c0f07b9b93d2ed741c3c0860c613173de7d39e7968022041376d520e9c0e1ad52248ddf4b22e12be8763007df977253ef45a4ca3bdb7c001475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220");
+               }
+
+               chan.pending_htlcs.push({
+                       let mut out = HTLCOutput{
+                               htlc_id: 0,
+                               outbound: false,
+                               amount_msat: 1000000,
+                               cltv_expiry: 500,
+                               payment_hash: [0; 32],
+                               state: HTLCState::Committed,
+                               pending_forward_state: None,
+                       };
+                       let mut sha = Sha256::new();
+                       sha.input(&hex_bytes("0000000000000000000000000000000000000000000000000000000000000000").unwrap());
+                       sha.result(&mut out.payment_hash);
+                       out
+               });
+               chan.pending_htlcs.push({
+                       let mut out = HTLCOutput{
+                               htlc_id: 1,
+                               outbound: false,
+                               amount_msat: 2000000,
+                               cltv_expiry: 501,
+                               payment_hash: [0; 32],
+                               state: HTLCState::Committed,
+                               pending_forward_state: None,
+                       };
+                       let mut sha = Sha256::new();
+                       sha.input(&hex_bytes("0101010101010101010101010101010101010101010101010101010101010101").unwrap());
+                       sha.result(&mut out.payment_hash);
+                       out
+               });
+               chan.pending_htlcs.push({
+                       let mut out = HTLCOutput{
+                               htlc_id: 2,
+                               outbound: true,
+                               amount_msat: 2000000,
+                               cltv_expiry: 502,
+                               payment_hash: [0; 32],
+                               state: HTLCState::Committed,
+                               pending_forward_state: None,
+                       };
+                       let mut sha = Sha256::new();
+                       sha.input(&hex_bytes("0202020202020202020202020202020202020202020202020202020202020202").unwrap());
+                       sha.result(&mut out.payment_hash);
+                       out
+               });
+               chan.pending_htlcs.push({
+                       let mut out = HTLCOutput{
+                               htlc_id: 3,
+                               outbound: true,
+                               amount_msat: 3000000,
+                               cltv_expiry: 503,
+                               payment_hash: [0; 32],
+                               state: HTLCState::Committed,
+                               pending_forward_state: None,
+                       };
+                       let mut sha = Sha256::new();
+                       sha.input(&hex_bytes("0303030303030303030303030303030303030303030303030303030303030303").unwrap());
+                       sha.result(&mut out.payment_hash);
+                       out
+               });
+               chan.pending_htlcs.push({
+                       let mut out = HTLCOutput{
+                               htlc_id: 4,
+                               outbound: false,
+                               amount_msat: 4000000,
+                               cltv_expiry: 504,
+                               payment_hash: [0; 32],
+                               state: HTLCState::Committed,
+                               pending_forward_state: None,
+                       };
+                       let mut sha = Sha256::new();
+                       sha.input(&hex_bytes("0404040404040404040404040404040404040404040404040404040404040404").unwrap());
+                       sha.result(&mut out.payment_hash);
+                       out
+               });
+
+               {
+                       // commitment tx with all five HTLCs untrimmed (minimum feerate)
+                       chan.value_to_self_msat = 6993000000; // 7000000000 - 7000000
+                       chan.feerate_per_kw = 0;
+
+                       test_commitment!("304402204fd4928835db1ccdfc40f5c78ce9bd65249b16348df81f0c44328dcdefc97d630220194d3869c38bc732dd87d13d2958015e2fc16829e74cd4377f84d215c0b70606",
+                                        "30440220275b0c325a5e9355650dc30c0eccfbc7efb23987c24b556b9dfdd40effca18d202206caceb2c067836c51f296740c7ae807ffcbfbf1dd3a0d56b6de9a5b247985f06",
+                                        "02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b8007e80300000000000022002052bfef0479d7b293c27e0f1eb294bea154c63a3294ef092c19af51409bce0e2ad007000000000000220020403d394747cae42e98ff01734ad5c08f82ba123d3d9a620abda88989651e2ab5d007000000000000220020748eba944fedc8827f6b06bc44678f93c0f9e6078b35c6331ed31e75f8ce0c2db80b000000000000220020c20b5d1f8584fd90443e7b7b720136174fa4b9333c261d04dbbd012635c0f419a00f0000000000002200208c48d15160397c9731df9bc3b236656efb6665fbfe92b4a6878e88a499f741c4c0c62d0000000000160014ccf1af2f2aabee14bb40fa3851ab2301de843110e0a06a00000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e04004730440220275b0c325a5e9355650dc30c0eccfbc7efb23987c24b556b9dfdd40effca18d202206caceb2c067836c51f296740c7ae807ffcbfbf1dd3a0d56b6de9a5b247985f060147304402204fd4928835db1ccdfc40f5c78ce9bd65249b16348df81f0c44328dcdefc97d630220194d3869c38bc732dd87d13d2958015e2fc16829e74cd4377f84d215c0b7060601475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220");
+
+                       assert_eq!(unsigned_tx.1.len(), 5);
+
+                       test_htlc_output!(0,
+                                         "304402206a6e59f18764a5bf8d4fa45eebc591566689441229c918b480fb2af8cc6a4aeb02205248f273be447684b33e3c8d1d85a8e0ca9fa0bae9ae33f0527ada9c162919a6",
+                                         "304402207cb324fa0de88f452ffa9389678127ebcf4cabe1dd848b8e076c1a1962bf34720220116ed922b12311bd602d67e60d2529917f21c5b82f25ff6506c0f87886b4dfd5",
+                                         "020000000001018154ecccf11a5fb56c39654c4deb4d2296f83c69268280b94d021370c94e219700000000000000000001e8030000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e050047304402206a6e59f18764a5bf8d4fa45eebc591566689441229c918b480fb2af8cc6a4aeb02205248f273be447684b33e3c8d1d85a8e0ca9fa0bae9ae33f0527ada9c162919a60147304402207cb324fa0de88f452ffa9389678127ebcf4cabe1dd848b8e076c1a1962bf34720220116ed922b12311bd602d67e60d2529917f21c5b82f25ff6506c0f87886b4dfd5012000000000000000000000000000000000000000000000000000000000000000008a76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a914b8bcb07f6344b42ab04250c86a6e8b75d3fdbbc688527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f401b175ac686800000000");
+
+                       test_htlc_output!(1,
+                                         "3045022100d5275b3619953cb0c3b5aa577f04bc512380e60fa551762ce3d7a1bb7401cff9022037237ab0dac3fe100cde094e82e2bed9ba0ed1bb40154b48e56aa70f259e608b",
+                                         "3045022100c89172099507ff50f4c925e6c5150e871fb6e83dd73ff9fbb72f6ce829a9633f02203a63821d9162e99f9be712a68f9e589483994feae2661e4546cd5b6cec007be5",
+                                         "020000000001018154ecccf11a5fb56c39654c4deb4d2296f83c69268280b94d021370c94e219701000000000000000001d0070000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500483045022100d5275b3619953cb0c3b5aa577f04bc512380e60fa551762ce3d7a1bb7401cff9022037237ab0dac3fe100cde094e82e2bed9ba0ed1bb40154b48e56aa70f259e608b01483045022100c89172099507ff50f4c925e6c5150e871fb6e83dd73ff9fbb72f6ce829a9633f02203a63821d9162e99f9be712a68f9e589483994feae2661e4546cd5b6cec007be501008576a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a914b43e1b38138a41b37f7cd9a1d274bc63e3a9b5d188ac6868f6010000");
+
+                       test_htlc_output!(2,
+                                         "304402201b63ec807771baf4fdff523c644080de17f1da478989308ad13a58b51db91d360220568939d38c9ce295adba15665fa68f51d967e8ed14a007b751540a80b325f202",
+                                         "3045022100def389deab09cee69eaa1ec14d9428770e45bcbe9feb46468ecf481371165c2f022015d2e3c46600b2ebba8dcc899768874cc6851fd1ecb3fffd15db1cc3de7e10da",
+                                         "020000000001018154ecccf11a5fb56c39654c4deb4d2296f83c69268280b94d021370c94e219702000000000000000001d0070000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e050047304402201b63ec807771baf4fdff523c644080de17f1da478989308ad13a58b51db91d360220568939d38c9ce295adba15665fa68f51d967e8ed14a007b751540a80b325f20201483045022100def389deab09cee69eaa1ec14d9428770e45bcbe9feb46468ecf481371165c2f022015d2e3c46600b2ebba8dcc899768874cc6851fd1ecb3fffd15db1cc3de7e10da012001010101010101010101010101010101010101010101010101010101010101018a76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a9144b6b2e5444c2639cc0fb7bcea5afba3f3cdce23988527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f501b175ac686800000000");
+
+                       test_htlc_output!(3,
+                                         "3045022100daee1808f9861b6c3ecd14f7b707eca02dd6bdfc714ba2f33bc8cdba507bb182022026654bf8863af77d74f51f4e0b62d461a019561bb12acb120d3f7195d148a554",
+                                         "30440220643aacb19bbb72bd2b635bc3f7375481f5981bace78cdd8319b2988ffcc6704202203d27784ec8ad51ed3bd517a05525a5139bb0b755dd719e0054332d186ac08727",
+                                         "020000000001018154ecccf11a5fb56c39654c4deb4d2296f83c69268280b94d021370c94e219703000000000000000001b80b0000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500483045022100daee1808f9861b6c3ecd14f7b707eca02dd6bdfc714ba2f33bc8cdba507bb182022026654bf8863af77d74f51f4e0b62d461a019561bb12acb120d3f7195d148a554014730440220643aacb19bbb72bd2b635bc3f7375481f5981bace78cdd8319b2988ffcc6704202203d27784ec8ad51ed3bd517a05525a5139bb0b755dd719e0054332d186ac0872701008576a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a9148a486ff2e31d6158bf39e2608864d63fefd09d5b88ac6868f7010000");
+
+                       test_htlc_output!(4,
+                                         "304402207e0410e45454b0978a623f36a10626ef17b27d9ad44e2760f98cfa3efb37924f0220220bd8acd43ecaa916a80bd4f919c495a2c58982ce7c8625153f8596692a801d",
+                                         "30440220549e80b4496803cbc4a1d09d46df50109f546d43fbbf86cd90b174b1484acd5402205f12a4f995cb9bded597eabfee195a285986aa6d93ae5bb72507ebc6a4e2349e",
+                                         "020000000001018154ecccf11a5fb56c39654c4deb4d2296f83c69268280b94d021370c94e219704000000000000000001a00f0000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e050047304402207e0410e45454b0978a623f36a10626ef17b27d9ad44e2760f98cfa3efb37924f0220220bd8acd43ecaa916a80bd4f919c495a2c58982ce7c8625153f8596692a801d014730440220549e80b4496803cbc4a1d09d46df50109f546d43fbbf86cd90b174b1484acd5402205f12a4f995cb9bded597eabfee195a285986aa6d93ae5bb72507ebc6a4e2349e012004040404040404040404040404040404040404040404040404040404040404048a76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a91418bc1a114ccf9c052d3d23e28d3b0a9d1227434288527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f801b175ac686800000000");
+               }
+
+               {
+                       // commitment tx with seven outputs untrimmed (maximum feerate)
+                       chan.value_to_self_msat = 6993000000; // 7000000000 - 7000000
+                       chan.feerate_per_kw = 647;
+
+                       test_commitment!("3045022100a5c01383d3ec646d97e40f44318d49def817fcd61a0ef18008a665b3e151785502203e648efddd5838981ef55ec954be69c4a652d021e6081a100d034de366815e9b",
+                                        "304502210094bfd8f5572ac0157ec76a9551b6c5216a4538c07cd13a51af4a54cb26fa14320220768efce8ce6f4a5efac875142ff19237c011343670adf9c7ac69704a120d1163",
+                                        "02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b8007e80300000000000022002052bfef0479d7b293c27e0f1eb294bea154c63a3294ef092c19af51409bce0e2ad007000000000000220020403d394747cae42e98ff01734ad5c08f82ba123d3d9a620abda88989651e2ab5d007000000000000220020748eba944fedc8827f6b06bc44678f93c0f9e6078b35c6331ed31e75f8ce0c2db80b000000000000220020c20b5d1f8584fd90443e7b7b720136174fa4b9333c261d04dbbd012635c0f419a00f0000000000002200208c48d15160397c9731df9bc3b236656efb6665fbfe92b4a6878e88a499f741c4c0c62d0000000000160014ccf1af2f2aabee14bb40fa3851ab2301de843110e09c6a00000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e040048304502210094bfd8f5572ac0157ec76a9551b6c5216a4538c07cd13a51af4a54cb26fa14320220768efce8ce6f4a5efac875142ff19237c011343670adf9c7ac69704a120d116301483045022100a5c01383d3ec646d97e40f44318d49def817fcd61a0ef18008a665b3e151785502203e648efddd5838981ef55ec954be69c4a652d021e6081a100d034de366815e9b01475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220");
+
+                       assert_eq!(unsigned_tx.1.len(), 5);
+
+                       test_htlc_output!(0,
+                                         "30440220385a5afe75632f50128cbb029ee95c80156b5b4744beddc729ad339c9ca432c802202ba5f48550cad3379ac75b9b4fedb86a35baa6947f16ba5037fb8b11ab343740",
+                                         "304402205999590b8a79fa346e003a68fd40366397119b2b0cdf37b149968d6bc6fbcc4702202b1e1fb5ab7864931caed4e732c359e0fe3d86a548b557be2246efb1708d579a",
+                                         "020000000001018323148ce2419f21ca3d6780053747715832e18ac780931a514b187768882bb60000000000000000000122020000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e05004730440220385a5afe75632f50128cbb029ee95c80156b5b4744beddc729ad339c9ca432c802202ba5f48550cad3379ac75b9b4fedb86a35baa6947f16ba5037fb8b11ab3437400147304402205999590b8a79fa346e003a68fd40366397119b2b0cdf37b149968d6bc6fbcc4702202b1e1fb5ab7864931caed4e732c359e0fe3d86a548b557be2246efb1708d579a012000000000000000000000000000000000000000000000000000000000000000008a76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a914b8bcb07f6344b42ab04250c86a6e8b75d3fdbbc688527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f401b175ac686800000000");
+
+                       test_htlc_output!(1,
+                                         "304402207ceb6678d4db33d2401fdc409959e57c16a6cb97a30261d9c61f29b8c58d34b90220084b4a17b4ca0e86f2d798b3698ca52de5621f2ce86f80bed79afa66874511b0",
+                                         "304402207ff03eb0127fc7c6cae49cc29e2a586b98d1e8969cf4a17dfa50b9c2647720b902205e2ecfda2252956c0ca32f175080e75e4e390e433feb1f8ce9f2ba55648a1dac",
+                                         "020000000001018323148ce2419f21ca3d6780053747715832e18ac780931a514b187768882bb60100000000000000000124060000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e050047304402207ceb6678d4db33d2401fdc409959e57c16a6cb97a30261d9c61f29b8c58d34b90220084b4a17b4ca0e86f2d798b3698ca52de5621f2ce86f80bed79afa66874511b00147304402207ff03eb0127fc7c6cae49cc29e2a586b98d1e8969cf4a17dfa50b9c2647720b902205e2ecfda2252956c0ca32f175080e75e4e390e433feb1f8ce9f2ba55648a1dac01008576a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a914b43e1b38138a41b37f7cd9a1d274bc63e3a9b5d188ac6868f6010000");
+
+                       test_htlc_output!(2,
+                                         "304402206a401b29a0dff0d18ec903502c13d83e7ec019450113f4a7655a4ce40d1f65ba0220217723a084e727b6ca0cc8b6c69c014a7e4a01fcdcba3e3993f462a3c574d833",
+                                         "3045022100d50d067ca625d54e62df533a8f9291736678d0b86c28a61bb2a80cf42e702d6e02202373dde7e00218eacdafb9415fe0e1071beec1857d1af3c6a201a44cbc47c877",
+                                         "020000000001018323148ce2419f21ca3d6780053747715832e18ac780931a514b187768882bb6020000000000000000010a060000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e050047304402206a401b29a0dff0d18ec903502c13d83e7ec019450113f4a7655a4ce40d1f65ba0220217723a084e727b6ca0cc8b6c69c014a7e4a01fcdcba3e3993f462a3c574d83301483045022100d50d067ca625d54e62df533a8f9291736678d0b86c28a61bb2a80cf42e702d6e02202373dde7e00218eacdafb9415fe0e1071beec1857d1af3c6a201a44cbc47c877012001010101010101010101010101010101010101010101010101010101010101018a76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a9144b6b2e5444c2639cc0fb7bcea5afba3f3cdce23988527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f501b175ac686800000000");
+
+                       test_htlc_output!(3,
+                                         "30450221009b1c987ba599ee3bde1dbca776b85481d70a78b681a8d84206723e2795c7cac002207aac84ad910f8598c4d1c0ea2e3399cf6627a4e3e90131315bc9f038451ce39d",
+                                         "3045022100db9dc65291077a52728c622987e9895b7241d4394d6dcb916d7600a3e8728c22022036ee3ee717ba0bb5c45ee84bc7bbf85c0f90f26ae4e4a25a6b4241afa8a3f1cb",
+                                         "020000000001018323148ce2419f21ca3d6780053747715832e18ac780931a514b187768882bb6030000000000000000010c0a0000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e05004830450221009b1c987ba599ee3bde1dbca776b85481d70a78b681a8d84206723e2795c7cac002207aac84ad910f8598c4d1c0ea2e3399cf6627a4e3e90131315bc9f038451ce39d01483045022100db9dc65291077a52728c622987e9895b7241d4394d6dcb916d7600a3e8728c22022036ee3ee717ba0bb5c45ee84bc7bbf85c0f90f26ae4e4a25a6b4241afa8a3f1cb01008576a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a9148a486ff2e31d6158bf39e2608864d63fefd09d5b88ac6868f7010000");
+
+                       test_htlc_output!(4,
+                                         "3045022100cc28030b59f0914f45b84caa983b6f8effa900c952310708c2b5b00781117022022027ba2ccdf94d03c6d48b327f183f6e28c8a214d089b9227f94ac4f85315274f0",
+                                         "304402202d1a3c0d31200265d2a2def2753ead4959ae20b4083e19553acfffa5dfab60bf022020ede134149504e15b88ab261a066de49848411e15e70f9e6a5462aec2949f8f",
+                                         "020000000001018323148ce2419f21ca3d6780053747715832e18ac780931a514b187768882bb604000000000000000001da0d0000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500483045022100cc28030b59f0914f45b84caa983b6f8effa900c952310708c2b5b00781117022022027ba2ccdf94d03c6d48b327f183f6e28c8a214d089b9227f94ac4f85315274f00147304402202d1a3c0d31200265d2a2def2753ead4959ae20b4083e19553acfffa5dfab60bf022020ede134149504e15b88ab261a066de49848411e15e70f9e6a5462aec2949f8f012004040404040404040404040404040404040404040404040404040404040404048a76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a91418bc1a114ccf9c052d3d23e28d3b0a9d1227434288527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f801b175ac686800000000");
+               }
+
+               {
+                       // commitment tx with six outputs untrimmed (minimum feerate)
+                       chan.value_to_self_msat = 6993000000; // 7000000000 - 7000000
+                       chan.feerate_per_kw = 648;
+
+                       test_commitment!("3044022072714e2fbb93cdd1c42eb0828b4f2eff143f717d8f26e79d6ada4f0dcb681bbe02200911be4e5161dd6ebe59ff1c58e1997c4aea804f81db6b698821db6093d7b057",
+                                        "3045022100a2270d5950c89ae0841233f6efea9c951898b301b2e89e0adbd2c687b9f32efa02207943d90f95b9610458e7c65a576e149750ff3accaacad004cd85e70b235e27de",
+                                        "02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b8006d007000000000000220020403d394747cae42e98ff01734ad5c08f82ba123d3d9a620abda88989651e2ab5d007000000000000220020748eba944fedc8827f6b06bc44678f93c0f9e6078b35c6331ed31e75f8ce0c2db80b000000000000220020c20b5d1f8584fd90443e7b7b720136174fa4b9333c261d04dbbd012635c0f419a00f0000000000002200208c48d15160397c9731df9bc3b236656efb6665fbfe92b4a6878e88a499f741c4c0c62d0000000000160014ccf1af2f2aabee14bb40fa3851ab2301de8431104e9d6a00000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0400483045022100a2270d5950c89ae0841233f6efea9c951898b301b2e89e0adbd2c687b9f32efa02207943d90f95b9610458e7c65a576e149750ff3accaacad004cd85e70b235e27de01473044022072714e2fbb93cdd1c42eb0828b4f2eff143f717d8f26e79d6ada4f0dcb681bbe02200911be4e5161dd6ebe59ff1c58e1997c4aea804f81db6b698821db6093d7b05701475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220");
+
+                       assert_eq!(unsigned_tx.1.len(), 4);
+
+                       test_htlc_output!(0,
+                                         "3044022062ef2e77591409d60d7817d9bb1e71d3c4a2931d1a6c7c8307422c84f001a251022022dad9726b0ae3fe92bda745a06f2c00f92342a186d84518588cf65f4dfaada8",
+                                         "3045022100a4c574f00411dd2f978ca5cdc1b848c311cd7849c087ad2f21a5bce5e8cc5ae90220090ae39a9bce2fb8bc879d7e9f9022df249f41e25e51f1a9bf6447a9eeffc098",
+                                         "02000000000101579c183eca9e8236a5d7f5dcd79cfec32c497fdc0ec61533cde99ecd436cadd10000000000000000000123060000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500473044022062ef2e77591409d60d7817d9bb1e71d3c4a2931d1a6c7c8307422c84f001a251022022dad9726b0ae3fe92bda745a06f2c00f92342a186d84518588cf65f4dfaada801483045022100a4c574f00411dd2f978ca5cdc1b848c311cd7849c087ad2f21a5bce5e8cc5ae90220090ae39a9bce2fb8bc879d7e9f9022df249f41e25e51f1a9bf6447a9eeffc09801008576a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a914b43e1b38138a41b37f7cd9a1d274bc63e3a9b5d188ac6868f6010000");
+
+                       test_htlc_output!(1,
+                                         "3045022100e968cbbb5f402ed389fdc7f6cd2a80ed650bb42c79aeb2a5678444af94f6c78502204b47a1cb24ab5b0b6fe69fe9cfc7dba07b9dd0d8b95f372c1d9435146a88f8d4",
+                                         "304402207679cf19790bea76a733d2fa0672bd43ab455687a068f815a3d237581f57139a0220683a1a799e102071c206b207735ca80f627ab83d6616b4bcd017c5d79ef3e7d0",
+                                         "02000000000101579c183eca9e8236a5d7f5dcd79cfec32c497fdc0ec61533cde99ecd436cadd10100000000000000000109060000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500483045022100e968cbbb5f402ed389fdc7f6cd2a80ed650bb42c79aeb2a5678444af94f6c78502204b47a1cb24ab5b0b6fe69fe9cfc7dba07b9dd0d8b95f372c1d9435146a88f8d40147304402207679cf19790bea76a733d2fa0672bd43ab455687a068f815a3d237581f57139a0220683a1a799e102071c206b207735ca80f627ab83d6616b4bcd017c5d79ef3e7d0012001010101010101010101010101010101010101010101010101010101010101018a76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a9144b6b2e5444c2639cc0fb7bcea5afba3f3cdce23988527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f501b175ac686800000000");
+
+                       test_htlc_output!(2,
+                                         "3045022100aa91932e305292cf9969cc23502bbf6cef83a5df39c95ad04a707c4f4fed5c7702207099fc0f3a9bfe1e7683c0e9aa5e76c5432eb20693bf4cb182f04d383dc9c8c2",
+                                         "304402200df76fea718745f3c529bac7fd37923e7309ce38b25c0781e4cf514dd9ef8dc802204172295739dbae9fe0474dcee3608e3433b4b2af3a2e6787108b02f894dcdda3",
+                                         "02000000000101579c183eca9e8236a5d7f5dcd79cfec32c497fdc0ec61533cde99ecd436cadd1020000000000000000010b0a0000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500483045022100aa91932e305292cf9969cc23502bbf6cef83a5df39c95ad04a707c4f4fed5c7702207099fc0f3a9bfe1e7683c0e9aa5e76c5432eb20693bf4cb182f04d383dc9c8c20147304402200df76fea718745f3c529bac7fd37923e7309ce38b25c0781e4cf514dd9ef8dc802204172295739dbae9fe0474dcee3608e3433b4b2af3a2e6787108b02f894dcdda301008576a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a9148a486ff2e31d6158bf39e2608864d63fefd09d5b88ac6868f7010000");
+
+                       test_htlc_output!(3,
+                                         "3044022035cac88040a5bba420b1c4257235d5015309113460bc33f2853cd81ca36e632402202fc94fd3e81e9d34a9d01782a0284f3044370d03d60f3fc041e2da088d2de58f",
+                                         "304402200daf2eb7afd355b4caf6fb08387b5f031940ea29d1a9f35071288a839c9039e4022067201b562456e7948616c13acb876b386b511599b58ac1d94d127f91c50463a6",
+                                         "02000000000101579c183eca9e8236a5d7f5dcd79cfec32c497fdc0ec61533cde99ecd436cadd103000000000000000001d90d0000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500473044022035cac88040a5bba420b1c4257235d5015309113460bc33f2853cd81ca36e632402202fc94fd3e81e9d34a9d01782a0284f3044370d03d60f3fc041e2da088d2de58f0147304402200daf2eb7afd355b4caf6fb08387b5f031940ea29d1a9f35071288a839c9039e4022067201b562456e7948616c13acb876b386b511599b58ac1d94d127f91c50463a6012004040404040404040404040404040404040404040404040404040404040404048a76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a91418bc1a114ccf9c052d3d23e28d3b0a9d1227434288527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f801b175ac686800000000");
+               }
+
+               {
+                       // commitment tx with six outputs untrimmed (maximum feerate)
+                       chan.value_to_self_msat = 6993000000; // 7000000000 - 7000000
+                       chan.feerate_per_kw = 2069;
+
+                       test_commitment!("3044022001d55e488b8b035b2dd29d50b65b530923a416d47f377284145bc8767b1b6a75022019bb53ddfe1cefaf156f924777eaaf8fdca1810695a7d0a247ad2afba8232eb4",
+                                        "304402203ca8f31c6a47519f83255dc69f1894d9a6d7476a19f498d31eaf0cd3a85eeb63022026fd92dc752b33905c4c838c528b692a8ad4ced959990b5d5ee2ff940fa90eea",
+                                        "02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b8006d007000000000000220020403d394747cae42e98ff01734ad5c08f82ba123d3d9a620abda88989651e2ab5d007000000000000220020748eba944fedc8827f6b06bc44678f93c0f9e6078b35c6331ed31e75f8ce0c2db80b000000000000220020c20b5d1f8584fd90443e7b7b720136174fa4b9333c261d04dbbd012635c0f419a00f0000000000002200208c48d15160397c9731df9bc3b236656efb6665fbfe92b4a6878e88a499f741c4c0c62d0000000000160014ccf1af2f2aabee14bb40fa3851ab2301de84311077956a00000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e040047304402203ca8f31c6a47519f83255dc69f1894d9a6d7476a19f498d31eaf0cd3a85eeb63022026fd92dc752b33905c4c838c528b692a8ad4ced959990b5d5ee2ff940fa90eea01473044022001d55e488b8b035b2dd29d50b65b530923a416d47f377284145bc8767b1b6a75022019bb53ddfe1cefaf156f924777eaaf8fdca1810695a7d0a247ad2afba8232eb401475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220");
+
+                       assert_eq!(unsigned_tx.1.len(), 4);
+
+                       test_htlc_output!(0,
+                                         "3045022100d1cf354de41c1369336cf85b225ed033f1f8982a01be503668df756a7e668b66022001254144fb4d0eecc61908fccc3388891ba17c5d7a1a8c62bdd307e5a513f992",
+                                         "3044022056eb1af429660e45a1b0b66568cb8c4a3aa7e4c9c292d5d6c47f86ebf2c8838f022065c3ac4ebe980ca7a41148569be4ad8751b0a724a41405697ec55035dae66402",
+                                         "02000000000101ca94a9ad516ebc0c4bdd7b6254871babfa978d5accafb554214137d398bfcf6a0000000000000000000175020000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500483045022100d1cf354de41c1369336cf85b225ed033f1f8982a01be503668df756a7e668b66022001254144fb4d0eecc61908fccc3388891ba17c5d7a1a8c62bdd307e5a513f99201473044022056eb1af429660e45a1b0b66568cb8c4a3aa7e4c9c292d5d6c47f86ebf2c8838f022065c3ac4ebe980ca7a41148569be4ad8751b0a724a41405697ec55035dae6640201008576a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a914b43e1b38138a41b37f7cd9a1d274bc63e3a9b5d188ac6868f6010000");
+
+                       test_htlc_output!(1,
+                                         "3045022100d065569dcb94f090345402736385efeb8ea265131804beac06dd84d15dd2d6880220664feb0b4b2eb985fadb6ec7dc58c9334ea88ce599a9be760554a2d4b3b5d9f4",
+                                         "3045022100914bb232cd4b2690ee3d6cb8c3713c4ac9c4fb925323068d8b07f67c8541f8d9022057152f5f1615b793d2d45aac7518989ae4fe970f28b9b5c77504799d25433f7f",
+                                         "02000000000101ca94a9ad516ebc0c4bdd7b6254871babfa978d5accafb554214137d398bfcf6a0100000000000000000122020000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500483045022100d065569dcb94f090345402736385efeb8ea265131804beac06dd84d15dd2d6880220664feb0b4b2eb985fadb6ec7dc58c9334ea88ce599a9be760554a2d4b3b5d9f401483045022100914bb232cd4b2690ee3d6cb8c3713c4ac9c4fb925323068d8b07f67c8541f8d9022057152f5f1615b793d2d45aac7518989ae4fe970f28b9b5c77504799d25433f7f012001010101010101010101010101010101010101010101010101010101010101018a76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a9144b6b2e5444c2639cc0fb7bcea5afba3f3cdce23988527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f501b175ac686800000000");
+
+                       test_htlc_output!(2,
+                                         "3045022100d4e69d363de993684eae7b37853c40722a4c1b4a7b588ad7b5d8a9b5006137a102207a069c628170ee34be5612747051bdcc087466dbaa68d5756ea81c10155aef18",
+                                         "304402200e362443f7af830b419771e8e1614fc391db3a4eb799989abfc5ab26d6fcd032022039ab0cad1c14dfbe9446bf847965e56fe016e0cbcf719fd18c1bfbf53ecbd9f9",
+                                         "02000000000101ca94a9ad516ebc0c4bdd7b6254871babfa978d5accafb554214137d398bfcf6a020000000000000000015d060000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500483045022100d4e69d363de993684eae7b37853c40722a4c1b4a7b588ad7b5d8a9b5006137a102207a069c628170ee34be5612747051bdcc087466dbaa68d5756ea81c10155aef180147304402200e362443f7af830b419771e8e1614fc391db3a4eb799989abfc5ab26d6fcd032022039ab0cad1c14dfbe9446bf847965e56fe016e0cbcf719fd18c1bfbf53ecbd9f901008576a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a9148a486ff2e31d6158bf39e2608864d63fefd09d5b88ac6868f7010000");
+
+                       test_htlc_output!(3,
+                                         "30450221008ec888e36e4a4b3dc2ed6b823319855b2ae03006ca6ae0d9aa7e24bfc1d6f07102203b0f78885472a67ff4fe5916c0bb669487d659527509516fc3a08e87a2cc0a7c",
+                                         "304402202c3e14282b84b02705dfd00a6da396c9fe8a8bcb1d3fdb4b20a4feba09440e8b02202b058b39aa9b0c865b22095edcd9ff1f71bbfe20aa4993755e54d042755ed0d5",
+                                         "02000000000101ca94a9ad516ebc0c4bdd7b6254871babfa978d5accafb554214137d398bfcf6a03000000000000000001f2090000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e05004830450221008ec888e36e4a4b3dc2ed6b823319855b2ae03006ca6ae0d9aa7e24bfc1d6f07102203b0f78885472a67ff4fe5916c0bb669487d659527509516fc3a08e87a2cc0a7c0147304402202c3e14282b84b02705dfd00a6da396c9fe8a8bcb1d3fdb4b20a4feba09440e8b02202b058b39aa9b0c865b22095edcd9ff1f71bbfe20aa4993755e54d042755ed0d5012004040404040404040404040404040404040404040404040404040404040404048a76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a91418bc1a114ccf9c052d3d23e28d3b0a9d1227434288527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f801b175ac686800000000");
+               }
+
+               {
+                       // commitment tx with five outputs untrimmed (minimum feerate)
+                       chan.value_to_self_msat = 6993000000; // 7000000000 - 7000000
+                       chan.feerate_per_kw = 2070;
+
+                       test_commitment!("3045022100f2377f7a67b7fc7f4e2c0c9e3a7de935c32417f5668eda31ea1db401b7dc53030220415fdbc8e91d0f735e70c21952342742e25249b0d062d43efbfc564499f37526",
+                                        "30440220443cb07f650aebbba14b8bc8d81e096712590f524c5991ac0ed3bbc8fd3bd0c7022028a635f548e3ca64b19b69b1ea00f05b22752f91daf0b6dab78e62ba52eb7fd0",
+                                        "02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b8005d007000000000000220020403d394747cae42e98ff01734ad5c08f82ba123d3d9a620abda88989651e2ab5b80b000000000000220020c20b5d1f8584fd90443e7b7b720136174fa4b9333c261d04dbbd012635c0f419a00f0000000000002200208c48d15160397c9731df9bc3b236656efb6665fbfe92b4a6878e88a499f741c4c0c62d0000000000160014ccf1af2f2aabee14bb40fa3851ab2301de843110da966a00000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e04004730440220443cb07f650aebbba14b8bc8d81e096712590f524c5991ac0ed3bbc8fd3bd0c7022028a635f548e3ca64b19b69b1ea00f05b22752f91daf0b6dab78e62ba52eb7fd001483045022100f2377f7a67b7fc7f4e2c0c9e3a7de935c32417f5668eda31ea1db401b7dc53030220415fdbc8e91d0f735e70c21952342742e25249b0d062d43efbfc564499f3752601475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220");
+
+                       assert_eq!(unsigned_tx.1.len(), 3);
+
+                       test_htlc_output!(0,
+                                         "3045022100eed143b1ee4bed5dc3cde40afa5db3e7354cbf9c44054b5f713f729356f08cf7022077161d171c2bbd9badf3c9934de65a4918de03bbac1450f715275f75b103f891",
+                                         "3045022100a0d043ed533e7fb1911e0553d31a8e2f3e6de19dbc035257f29d747c5e02f1f5022030cd38d8e84282175d49c1ebe0470db3ebd59768cf40780a784e248a43904fb8",
+                                         "0200000000010140a83ce364747ff277f4d7595d8d15f708418798922c40bc2b056aca5485a2180000000000000000000174020000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500483045022100eed143b1ee4bed5dc3cde40afa5db3e7354cbf9c44054b5f713f729356f08cf7022077161d171c2bbd9badf3c9934de65a4918de03bbac1450f715275f75b103f89101483045022100a0d043ed533e7fb1911e0553d31a8e2f3e6de19dbc035257f29d747c5e02f1f5022030cd38d8e84282175d49c1ebe0470db3ebd59768cf40780a784e248a43904fb801008576a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a914b43e1b38138a41b37f7cd9a1d274bc63e3a9b5d188ac6868f6010000");
+
+                       test_htlc_output!(1,
+                                         "3044022071e9357619fd8d29a411dc053b326a5224c5d11268070e88ecb981b174747c7a02202b763ae29a9d0732fa8836dd8597439460b50472183f420021b768981b4f7cf6",
+                                         "3045022100adb1d679f65f96178b59f23ed37d3b70443118f345224a07ecb043eee2acc157022034d24524fe857144a3bcfff3065a9994d0a6ec5f11c681e49431d573e242612d",
+                                         "0200000000010140a83ce364747ff277f4d7595d8d15f708418798922c40bc2b056aca5485a218010000000000000000015c060000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500473044022071e9357619fd8d29a411dc053b326a5224c5d11268070e88ecb981b174747c7a02202b763ae29a9d0732fa8836dd8597439460b50472183f420021b768981b4f7cf601483045022100adb1d679f65f96178b59f23ed37d3b70443118f345224a07ecb043eee2acc157022034d24524fe857144a3bcfff3065a9994d0a6ec5f11c681e49431d573e242612d01008576a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a9148a486ff2e31d6158bf39e2608864d63fefd09d5b88ac6868f7010000");
+
+                       test_htlc_output!(2,
+                                         "3045022100c9458a4d2cbb741705577deb0a890e5cb90ee141be0400d3162e533727c9cb2102206edcf765c5dc5e5f9b976ea8149bf8607b5a0efb30691138e1231302b640d2a4",
+                                         "304402200831422aa4e1ee6d55e0b894201770a8f8817a189356f2d70be76633ffa6a6f602200dd1b84a4855dc6727dd46c98daae43dfc70889d1ba7ef0087529a57c06e5e04",
+                                         "0200000000010140a83ce364747ff277f4d7595d8d15f708418798922c40bc2b056aca5485a21802000000000000000001f1090000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500483045022100c9458a4d2cbb741705577deb0a890e5cb90ee141be0400d3162e533727c9cb2102206edcf765c5dc5e5f9b976ea8149bf8607b5a0efb30691138e1231302b640d2a40147304402200831422aa4e1ee6d55e0b894201770a8f8817a189356f2d70be76633ffa6a6f602200dd1b84a4855dc6727dd46c98daae43dfc70889d1ba7ef0087529a57c06e5e04012004040404040404040404040404040404040404040404040404040404040404048a76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a91418bc1a114ccf9c052d3d23e28d3b0a9d1227434288527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f801b175ac686800000000");
+               }
+
+               {
+                       // commitment tx with five outputs untrimmed (maximum feerate)
+                       chan.value_to_self_msat = 6993000000; // 7000000000 - 7000000
+                       chan.feerate_per_kw = 2194;
+
+                       test_commitment!("3045022100d33c4e541aa1d255d41ea9a3b443b3b822ad8f7f86862638aac1f69f8f760577022007e2a18e6931ce3d3a804b1c78eda1de17dbe1fb7a95488c9a4ec86203953348",
+                                        "304402203b1b010c109c2ecbe7feb2d259b9c4126bd5dc99ee693c422ec0a5781fe161ba0220571fe4e2c649dea9c7aaf7e49b382962f6a3494963c97d80fef9a430ca3f7061",
+                                        "02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b8005d007000000000000220020403d394747cae42e98ff01734ad5c08f82ba123d3d9a620abda88989651e2ab5b80b000000000000220020c20b5d1f8584fd90443e7b7b720136174fa4b9333c261d04dbbd012635c0f419a00f0000000000002200208c48d15160397c9731df9bc3b236656efb6665fbfe92b4a6878e88a499f741c4c0c62d0000000000160014ccf1af2f2aabee14bb40fa3851ab2301de84311040966a00000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e040047304402203b1b010c109c2ecbe7feb2d259b9c4126bd5dc99ee693c422ec0a5781fe161ba0220571fe4e2c649dea9c7aaf7e49b382962f6a3494963c97d80fef9a430ca3f706101483045022100d33c4e541aa1d255d41ea9a3b443b3b822ad8f7f86862638aac1f69f8f760577022007e2a18e6931ce3d3a804b1c78eda1de17dbe1fb7a95488c9a4ec8620395334801475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220");
+
+                       assert_eq!(unsigned_tx.1.len(), 3);
+
+                       test_htlc_output!(0,
+                                         "30450221009ed2f0a67f99e29c3c8cf45c08207b765980697781bb727fe0b1416de0e7622902206052684229bc171419ed290f4b615c943f819c0262414e43c5b91dcf72ddcf44",
+                                         "3044022004ad5f04ae69c71b3b141d4db9d0d4c38d84009fb3cfeeae6efdad414487a9a0022042d3fe1388c1ff517d1da7fb4025663d372c14728ed52dc88608363450ff6a2f",
+                                         "02000000000101fb824d4e4dafc0f567789dee3a6bce8d411fe80f5563d8cdfdcc7d7e4447d43a0000000000000000000122020000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e05004830450221009ed2f0a67f99e29c3c8cf45c08207b765980697781bb727fe0b1416de0e7622902206052684229bc171419ed290f4b615c943f819c0262414e43c5b91dcf72ddcf4401473044022004ad5f04ae69c71b3b141d4db9d0d4c38d84009fb3cfeeae6efdad414487a9a0022042d3fe1388c1ff517d1da7fb4025663d372c14728ed52dc88608363450ff6a2f01008576a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a914b43e1b38138a41b37f7cd9a1d274bc63e3a9b5d188ac6868f6010000");
+
+                       test_htlc_output!(1,
+                                         "30440220155d3b90c67c33a8321996a9be5b82431b0c126613be751d400669da9d5c696702204318448bcd48824439d2c6a70be6e5747446be47ff45977cf41672bdc9b6b12d",
+                                         "304402201707050c870c1f77cc3ed58d6d71bf281de239e9eabd8ef0955bad0d7fe38dcc02204d36d80d0019b3a71e646a08fa4a5607761d341ae8be371946ebe437c289c915",
+                                         "02000000000101fb824d4e4dafc0f567789dee3a6bce8d411fe80f5563d8cdfdcc7d7e4447d43a010000000000000000010a060000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e05004730440220155d3b90c67c33a8321996a9be5b82431b0c126613be751d400669da9d5c696702204318448bcd48824439d2c6a70be6e5747446be47ff45977cf41672bdc9b6b12d0147304402201707050c870c1f77cc3ed58d6d71bf281de239e9eabd8ef0955bad0d7fe38dcc02204d36d80d0019b3a71e646a08fa4a5607761d341ae8be371946ebe437c289c91501008576a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a9148a486ff2e31d6158bf39e2608864d63fefd09d5b88ac6868f7010000");
+
+                       test_htlc_output!(2,
+                                         "3045022100a12a9a473ece548584aabdd051779025a5ed4077c4b7aa376ec7a0b1645e5a48022039490b333f53b5b3e2ddde1d809e492cba2b3e5fc3a436cd3ffb4cd3d500fa5a",
+                                         "3045022100ff200bc934ab26ce9a559e998ceb0aee53bc40368e114ab9d3054d9960546e2802202496856ca163ac12c143110b6b3ac9d598df7254f2e17b3b94c3ab5301f4c3b0",
+                                         "02000000000101fb824d4e4dafc0f567789dee3a6bce8d411fe80f5563d8cdfdcc7d7e4447d43a020000000000000000019a090000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500483045022100a12a9a473ece548584aabdd051779025a5ed4077c4b7aa376ec7a0b1645e5a48022039490b333f53b5b3e2ddde1d809e492cba2b3e5fc3a436cd3ffb4cd3d500fa5a01483045022100ff200bc934ab26ce9a559e998ceb0aee53bc40368e114ab9d3054d9960546e2802202496856ca163ac12c143110b6b3ac9d598df7254f2e17b3b94c3ab5301f4c3b0012004040404040404040404040404040404040404040404040404040404040404048a76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a91418bc1a114ccf9c052d3d23e28d3b0a9d1227434288527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f801b175ac686800000000");
+               }
+
+               {
+                       // commitment tx with four outputs untrimmed (minimum feerate)
+                       chan.value_to_self_msat = 6993000000; // 7000000000 - 7000000
+                       chan.feerate_per_kw = 2195;
+
+                       test_commitment!("304402205e2f76d4657fb732c0dfc820a18a7301e368f5799e06b7828007633741bda6df0220458009ae59d0c6246065c419359e05eb2a4b4ef4a1b310cc912db44eb7924298",
+                                        "304402203b12d44254244b8ff3bb4129b0920fd45120ab42f553d9976394b099d500c99e02205e95bb7a3164852ef0c48f9e0eaf145218f8e2c41251b231f03cbdc4f29a5429",
+                                        "02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b8004b80b000000000000220020c20b5d1f8584fd90443e7b7b720136174fa4b9333c261d04dbbd012635c0f419a00f0000000000002200208c48d15160397c9731df9bc3b236656efb6665fbfe92b4a6878e88a499f741c4c0c62d0000000000160014ccf1af2f2aabee14bb40fa3851ab2301de843110b8976a00000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e040047304402203b12d44254244b8ff3bb4129b0920fd45120ab42f553d9976394b099d500c99e02205e95bb7a3164852ef0c48f9e0eaf145218f8e2c41251b231f03cbdc4f29a54290147304402205e2f76d4657fb732c0dfc820a18a7301e368f5799e06b7828007633741bda6df0220458009ae59d0c6246065c419359e05eb2a4b4ef4a1b310cc912db44eb792429801475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220");
+
+                       assert_eq!(unsigned_tx.1.len(), 2);
+
+                       test_htlc_output!(0,
+                                         "3045022100a8a78fa1016a5c5c3704f2e8908715a3cef66723fb95f3132ec4d2d05cd84fb4022025ac49287b0861ec21932405f5600cbce94313dbde0e6c5d5af1b3366d8afbfc",
+                                         "3045022100be6ae1977fd7b630a53623f3f25c542317ccfc2b971782802a4f1ef538eb22b402207edc4d0408f8f38fd3c7365d1cfc26511b7cd2d4fecd8b005fba3cd5bc704390",
+                                         "020000000001014e16c488fa158431c1a82e8f661240ec0a71ba0ce92f2721a6538c510226ad5c0000000000000000000109060000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500483045022100a8a78fa1016a5c5c3704f2e8908715a3cef66723fb95f3132ec4d2d05cd84fb4022025ac49287b0861ec21932405f5600cbce94313dbde0e6c5d5af1b3366d8afbfc01483045022100be6ae1977fd7b630a53623f3f25c542317ccfc2b971782802a4f1ef538eb22b402207edc4d0408f8f38fd3c7365d1cfc26511b7cd2d4fecd8b005fba3cd5bc70439001008576a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a9148a486ff2e31d6158bf39e2608864d63fefd09d5b88ac6868f7010000");
+
+                       test_htlc_output!(1,
+                                         "3045022100e769cb156aa2f7515d126cef7a69968629620ce82afcaa9e210969de6850df4602200b16b3f3486a229a48aadde520dbee31ae340dbadaffae74fbb56681fef27b92",
+                                         "30440220665b9cb4a978c09d1ca8977a534999bc8a49da624d0c5439451dd69cde1a003d022070eae0620f01f3c1bd029cc1488da13fb40fdab76f396ccd335479a11c5276d8",
+                                         "020000000001014e16c488fa158431c1a82e8f661240ec0a71ba0ce92f2721a6538c510226ad5c0100000000000000000199090000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500483045022100e769cb156aa2f7515d126cef7a69968629620ce82afcaa9e210969de6850df4602200b16b3f3486a229a48aadde520dbee31ae340dbadaffae74fbb56681fef27b92014730440220665b9cb4a978c09d1ca8977a534999bc8a49da624d0c5439451dd69cde1a003d022070eae0620f01f3c1bd029cc1488da13fb40fdab76f396ccd335479a11c5276d8012004040404040404040404040404040404040404040404040404040404040404048a76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a91418bc1a114ccf9c052d3d23e28d3b0a9d1227434288527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f801b175ac686800000000");
+               }
+
+               {
+                       // commitment tx with four outputs untrimmed (maximum feerate)
+                       chan.value_to_self_msat = 6993000000; // 7000000000 - 7000000
+                       chan.feerate_per_kw = 3702;
+
+                       test_commitment!("3045022100c1a3b0b60ca092ed5080121f26a74a20cec6bdee3f8e47bae973fcdceb3eda5502207d467a9873c939bf3aa758014ae67295fedbca52412633f7e5b2670fc7c381c1",
+                                        "304402200e930a43c7951162dc15a2b7344f48091c74c70f7024e7116e900d8bcfba861c022066fa6cbda3929e21daa2e7e16a4b948db7e8919ef978402360d1095ffdaff7b0",
+                                        "02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b8004b80b000000000000220020c20b5d1f8584fd90443e7b7b720136174fa4b9333c261d04dbbd012635c0f419a00f0000000000002200208c48d15160397c9731df9bc3b236656efb6665fbfe92b4a6878e88a499f741c4c0c62d0000000000160014ccf1af2f2aabee14bb40fa3851ab2301de8431106f916a00000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e040047304402200e930a43c7951162dc15a2b7344f48091c74c70f7024e7116e900d8bcfba861c022066fa6cbda3929e21daa2e7e16a4b948db7e8919ef978402360d1095ffdaff7b001483045022100c1a3b0b60ca092ed5080121f26a74a20cec6bdee3f8e47bae973fcdceb3eda5502207d467a9873c939bf3aa758014ae67295fedbca52412633f7e5b2670fc7c381c101475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220");
+
+                       assert_eq!(unsigned_tx.1.len(), 2);
+
+                       test_htlc_output!(0,
+                                         "3045022100dfb73b4fe961b31a859b2bb1f4f15cabab9265016dd0272323dc6a9e85885c54022059a7b87c02861ee70662907f25ce11597d7b68d3399443a831ae40e777b76bdb",
+                                         "304402202765b9c9ece4f127fa5407faf66da4c5ce2719cdbe47cd3175fc7d48b482e43d02205605125925e07bad1e41c618a4b434d72c88a164981c4b8af5eaf4ee9142ec3a",
+                                         "02000000000101b8de11eb51c22498fe39722c7227b6e55ff1a94146cf638458cb9bc6a060d3a30000000000000000000122020000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500483045022100dfb73b4fe961b31a859b2bb1f4f15cabab9265016dd0272323dc6a9e85885c54022059a7b87c02861ee70662907f25ce11597d7b68d3399443a831ae40e777b76bdb0147304402202765b9c9ece4f127fa5407faf66da4c5ce2719cdbe47cd3175fc7d48b482e43d02205605125925e07bad1e41c618a4b434d72c88a164981c4b8af5eaf4ee9142ec3a01008576a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a9148a486ff2e31d6158bf39e2608864d63fefd09d5b88ac6868f7010000");
+
+                       test_htlc_output!(1,
+                                         "3045022100ea9dc2a7c3c3640334dab733bb4e036e32a3106dc707b24227874fa4f7da746802204d672f7ac0fe765931a8df10b81e53a3242dd32bd9dc9331eb4a596da87954e9",
+                                         "30440220048a41c660c4841693de037d00a407810389f4574b3286afb7bc392a438fa3f802200401d71fa87c64fe621b49ac07e3bf85157ac680acb977124da28652cc7f1a5c",
+                                         "02000000000101b8de11eb51c22498fe39722c7227b6e55ff1a94146cf638458cb9bc6a060d3a30100000000000000000176050000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500483045022100ea9dc2a7c3c3640334dab733bb4e036e32a3106dc707b24227874fa4f7da746802204d672f7ac0fe765931a8df10b81e53a3242dd32bd9dc9331eb4a596da87954e9014730440220048a41c660c4841693de037d00a407810389f4574b3286afb7bc392a438fa3f802200401d71fa87c64fe621b49ac07e3bf85157ac680acb977124da28652cc7f1a5c012004040404040404040404040404040404040404040404040404040404040404048a76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a91418bc1a114ccf9c052d3d23e28d3b0a9d1227434288527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f801b175ac686800000000");
+               }
+
+               {
+                       // commitment tx with three outputs untrimmed (minimum feerate)
+                       chan.value_to_self_msat = 6993000000; // 7000000000 - 7000000
+                       chan.feerate_per_kw = 3703;
+
+                       test_commitment!("30450221008b7c191dd46893b67b628e618d2dc8e81169d38bade310181ab77d7c94c6675e02203b4dd131fd7c9deb299560983dcdc485545c98f989f7ae8180c28289f9e6bdb0",
+                                        "3044022047305531dd44391dce03ae20f8735005c615eb077a974edb0059ea1a311857d602202e0ed6972fbdd1e8cb542b06e0929bc41b2ddf236e04cb75edd56151f4197506",
+                                        "02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b8003a00f0000000000002200208c48d15160397c9731df9bc3b236656efb6665fbfe92b4a6878e88a499f741c4c0c62d0000000000160014ccf1af2f2aabee14bb40fa3851ab2301de843110eb936a00000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0400473044022047305531dd44391dce03ae20f8735005c615eb077a974edb0059ea1a311857d602202e0ed6972fbdd1e8cb542b06e0929bc41b2ddf236e04cb75edd56151f4197506014830450221008b7c191dd46893b67b628e618d2dc8e81169d38bade310181ab77d7c94c6675e02203b4dd131fd7c9deb299560983dcdc485545c98f989f7ae8180c28289f9e6bdb001475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220");
+
+                       assert_eq!(unsigned_tx.1.len(), 1);
+
+                       test_htlc_output!(0,
+                                         "3044022044f65cf833afdcb9d18795ca93f7230005777662539815b8a601eeb3e57129a902206a4bf3e53392affbba52640627defa8dc8af61c958c9e827b2798ab45828abdd",
+                                         "3045022100b94d931a811b32eeb885c28ddcf999ae1981893b21dd1329929543fe87ce793002206370107fdd151c5f2384f9ceb71b3107c69c74c8ed5a28a94a4ab2d27d3b0724",
+                                         "020000000001011c076aa7fb3d7460d10df69432c904227ea84bbf3134d4ceee5fb0f135ef206d0000000000000000000175050000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500473044022044f65cf833afdcb9d18795ca93f7230005777662539815b8a601eeb3e57129a902206a4bf3e53392affbba52640627defa8dc8af61c958c9e827b2798ab45828abdd01483045022100b94d931a811b32eeb885c28ddcf999ae1981893b21dd1329929543fe87ce793002206370107fdd151c5f2384f9ceb71b3107c69c74c8ed5a28a94a4ab2d27d3b0724012004040404040404040404040404040404040404040404040404040404040404048a76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a91418bc1a114ccf9c052d3d23e28d3b0a9d1227434288527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f801b175ac686800000000");
+               }
+
+               {
+                       // commitment tx with three outputs untrimmed (maximum feerate)
+                       chan.value_to_self_msat = 6993000000; // 7000000000 - 7000000
+                       chan.feerate_per_kw = 4914;
+
+                       test_commitment!("304402206d6cb93969d39177a09d5d45b583f34966195b77c7e585cf47ac5cce0c90cefb022031d71ae4e33a4e80df7f981d696fbdee517337806a3c7138b7491e2cbb077a0e",
+                                        "304402206a2679efa3c7aaffd2a447fd0df7aba8792858b589750f6a1203f9259173198a022008d52a0e77a99ab533c36206cb15ad7aeb2aa72b93d4b571e728cb5ec2f6fe26",
+                                        "02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b8003a00f0000000000002200208c48d15160397c9731df9bc3b236656efb6665fbfe92b4a6878e88a499f741c4c0c62d0000000000160014ccf1af2f2aabee14bb40fa3851ab2301de843110ae8f6a00000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e040047304402206a2679efa3c7aaffd2a447fd0df7aba8792858b589750f6a1203f9259173198a022008d52a0e77a99ab533c36206cb15ad7aeb2aa72b93d4b571e728cb5ec2f6fe260147304402206d6cb93969d39177a09d5d45b583f34966195b77c7e585cf47ac5cce0c90cefb022031d71ae4e33a4e80df7f981d696fbdee517337806a3c7138b7491e2cbb077a0e01475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220");
+
+                       assert_eq!(unsigned_tx.1.len(), 1);
+
+                       test_htlc_output!(0,
+                                         "3045022100fcb38506bfa11c02874092a843d0cc0a8613c23b639832564a5f69020cb0f6ba02206508b9e91eaa001425c190c68ee5f887e1ad5b1b314002e74db9dbd9e42dbecf",
+                                         "304502210086e76b460ddd3cea10525fba298405d3fe11383e56966a5091811368362f689a02200f72ee75657915e0ede89c28709acd113ede9e1b7be520e3bc5cda425ecd6e68",
+                                         "0200000000010110a3fdcbcd5db477cd3ad465e7f501ffa8c437e8301f00a6061138590add757f0000000000000000000122020000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500483045022100fcb38506bfa11c02874092a843d0cc0a8613c23b639832564a5f69020cb0f6ba02206508b9e91eaa001425c190c68ee5f887e1ad5b1b314002e74db9dbd9e42dbecf0148304502210086e76b460ddd3cea10525fba298405d3fe11383e56966a5091811368362f689a02200f72ee75657915e0ede89c28709acd113ede9e1b7be520e3bc5cda425ecd6e68012004040404040404040404040404040404040404040404040404040404040404048a76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a91418bc1a114ccf9c052d3d23e28d3b0a9d1227434288527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f801b175ac686800000000");
+               }
+
+               {
+                       // commitment tx with two outputs untrimmed (minimum feerate)
+                       chan.value_to_self_msat = 6993000000; // 7000000000 - 7000000
+                       chan.feerate_per_kw = 4915;
+
+                       test_commitment!("304402200769ba89c7330dfa4feba447b6e322305f12ac7dac70ec6ba997ed7c1b598d0802204fe8d337e7fee781f9b7b1a06e580b22f4f79d740059560191d7db53f8765552",
+                                        "3045022100a012691ba6cea2f73fa8bac37750477e66363c6d28813b0bb6da77c8eb3fb0270220365e99c51304b0b1a6ab9ea1c8500db186693e39ec1ad5743ee231b0138384b9",
+                                        "02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b8002c0c62d0000000000160014ccf1af2f2aabee14bb40fa3851ab2301de843110fa926a00000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0400483045022100a012691ba6cea2f73fa8bac37750477e66363c6d28813b0bb6da77c8eb3fb0270220365e99c51304b0b1a6ab9ea1c8500db186693e39ec1ad5743ee231b0138384b90147304402200769ba89c7330dfa4feba447b6e322305f12ac7dac70ec6ba997ed7c1b598d0802204fe8d337e7fee781f9b7b1a06e580b22f4f79d740059560191d7db53f876555201475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220");
+
+                       assert_eq!(unsigned_tx.1.len(), 0);
+               }
+
+               {
+                       // commitment tx with two outputs untrimmed (maximum feerate)
+                       chan.value_to_self_msat = 6993000000; // 7000000000 - 7000000
+                       chan.feerate_per_kw = 9651180;
+
+                       test_commitment!("3044022037f83ff00c8e5fb18ae1f918ffc24e54581775a20ff1ae719297ef066c71caa9022039c529cccd89ff6c5ed1db799614533844bd6d101da503761c45c713996e3bbd",
+                                        "30440220514f977bf7edc442de8ce43ace9686e5ebdc0f893033f13e40fb46c8b8c6e1f90220188006227d175f5c35da0b092c57bea82537aed89f7778204dc5bacf4f29f2b9",
+                                        "02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b800222020000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80ec0c62d0000000000160014ccf1af2f2aabee14bb40fa3851ab2301de84311004004730440220514f977bf7edc442de8ce43ace9686e5ebdc0f893033f13e40fb46c8b8c6e1f90220188006227d175f5c35da0b092c57bea82537aed89f7778204dc5bacf4f29f2b901473044022037f83ff00c8e5fb18ae1f918ffc24e54581775a20ff1ae719297ef066c71caa9022039c529cccd89ff6c5ed1db799614533844bd6d101da503761c45c713996e3bbd01475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220");
+
+                       assert_eq!(unsigned_tx.1.len(), 0);
+               }
+
+               {
+                       // commitment tx with one output untrimmed (minimum feerate)
+                       chan.value_to_self_msat = 6993000000; // 7000000000 - 7000000
+                       chan.feerate_per_kw = 9651181;
+
+                       test_commitment!("3044022064901950be922e62cbe3f2ab93de2b99f37cff9fc473e73e394b27f88ef0731d02206d1dfa227527b4df44a07599289e207d6fd9cca60c0365682dcd3deaf739567e",
+                                        "3044022031a82b51bd014915fe68928d1abf4b9885353fb896cac10c3fdd88d7f9c7f2e00220716bda819641d2c63e65d3549b6120112e1aeaf1742eed94a471488e79e206b1",
+                                        "02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b8001c0c62d0000000000160014ccf1af2f2aabee14bb40fa3851ab2301de8431100400473044022031a82b51bd014915fe68928d1abf4b9885353fb896cac10c3fdd88d7f9c7f2e00220716bda819641d2c63e65d3549b6120112e1aeaf1742eed94a471488e79e206b101473044022064901950be922e62cbe3f2ab93de2b99f37cff9fc473e73e394b27f88ef0731d02206d1dfa227527b4df44a07599289e207d6fd9cca60c0365682dcd3deaf739567e01475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220");
+
+                       assert_eq!(unsigned_tx.1.len(), 0);
+               }
+
+               {
+                       // commitment tx with fee greater than funder amount
+                       chan.value_to_self_msat = 6993000000; // 7000000000 - 7000000
+                       chan.feerate_per_kw = 9651936;
+
+                       test_commitment!("3044022064901950be922e62cbe3f2ab93de2b99f37cff9fc473e73e394b27f88ef0731d02206d1dfa227527b4df44a07599289e207d6fd9cca60c0365682dcd3deaf739567e",
+                                        "3044022031a82b51bd014915fe68928d1abf4b9885353fb896cac10c3fdd88d7f9c7f2e00220716bda819641d2c63e65d3549b6120112e1aeaf1742eed94a471488e79e206b1",
+                                        "02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b8001c0c62d0000000000160014ccf1af2f2aabee14bb40fa3851ab2301de8431100400473044022031a82b51bd014915fe68928d1abf4b9885353fb896cac10c3fdd88d7f9c7f2e00220716bda819641d2c63e65d3549b6120112e1aeaf1742eed94a471488e79e206b101473044022064901950be922e62cbe3f2ab93de2b99f37cff9fc473e73e394b27f88ef0731d02206d1dfa227527b4df44a07599289e207d6fd9cca60c0365682dcd3deaf739567e01475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220");
+
+                       assert_eq!(unsigned_tx.1.len(), 0);
+               }
+       }
+
+       #[test]
+       fn test_per_commitment_secret_gen() {
+               // Test vectors from BOLT 3 Appendix D:
+
+               let mut seed = [0; 32];
+               seed[0..32].clone_from_slice(&hex_bytes("0000000000000000000000000000000000000000000000000000000000000000").unwrap());
+               assert_eq!(chan_utils::build_commitment_secret(seed, 281474976710655),
+                               hex_bytes("02a40c85b6f28da08dfdbe0926c53fab2de6d28c10301f8f7c4073d5e42e3148").unwrap()[..]);
+
+               seed[0..32].clone_from_slice(&hex_bytes("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF").unwrap());
+               assert_eq!(chan_utils::build_commitment_secret(seed, 281474976710655),
+                               hex_bytes("7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc").unwrap()[..]);
+
+               assert_eq!(chan_utils::build_commitment_secret(seed, 0xaaaaaaaaaaa),
+                               hex_bytes("56f4008fb007ca9acf0e15b054d5c9fd12ee06cea347914ddbaed70d1c13a528").unwrap()[..]);
+
+               assert_eq!(chan_utils::build_commitment_secret(seed, 0x555555555555),
+                               hex_bytes("9015daaeb06dba4ccc05b91b2f73bd54405f2be9f217fbacd3c5ac2e62327d31").unwrap()[..]);
+
+               seed[0..32].clone_from_slice(&hex_bytes("0101010101010101010101010101010101010101010101010101010101010101").unwrap());
+               assert_eq!(chan_utils::build_commitment_secret(seed, 1),
+                               hex_bytes("915c75942a26bb3a433a8ce2cb0427c29ec6c1775cfc78328b57f6ba7bfeaa9c").unwrap()[..]);
+       }
+
+       #[test]
+       fn test_key_derivation() {
+               // Test vectors from BOLT 3 Appendix E:
+               let secp_ctx = Secp256k1::new();
+
+               let base_secret = SecretKey::from_slice(&secp_ctx, &hex_bytes("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f").unwrap()[..]).unwrap();
+               let per_commitment_secret = SecretKey::from_slice(&secp_ctx, &hex_bytes("1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100").unwrap()[..]).unwrap();
+
+               let base_point = PublicKey::from_secret_key(&secp_ctx, &base_secret).unwrap();
+               assert_eq!(base_point.serialize()[..], hex_bytes("036d6caac248af96f6afa7f904f550253a0f3ef3f5aa2fe6838a95b216691468e2").unwrap()[..]);
+
+               let per_commitment_point = PublicKey::from_secret_key(&secp_ctx, &per_commitment_secret).unwrap();
+               assert_eq!(per_commitment_point.serialize()[..], hex_bytes("025f7117a78150fe2ef97db7cfc83bd57b2e2c0d0dd25eaf467a4a1c2a45ce1486").unwrap()[..]);
+
+               assert_eq!(chan_utils::derive_public_key(&secp_ctx, &per_commitment_point, &base_point).unwrap().serialize()[..],
+                               hex_bytes("0235f2dbfaa89b57ec7b055afe29849ef7ddfeb1cefdb9ebdc43f5494984db29e5").unwrap()[..]);
+
+               assert_eq!(chan_utils::derive_private_key(&secp_ctx, &per_commitment_point, &base_secret).unwrap(),
+                               SecretKey::from_slice(&secp_ctx, &hex_bytes("cbced912d3b21bf196a766651e436aff192362621ce317704ea2f75d87e7be0f").unwrap()[..]).unwrap());
+
+               assert_eq!(chan_utils::derive_public_revocation_key(&secp_ctx, &per_commitment_point, &base_point).unwrap().serialize()[..],
+                               hex_bytes("02916e326636d19c33f13e8c0c3a03dd157f332f3e99c317c141dd865eb01f8ff0").unwrap()[..]);
+
+               assert_eq!(chan_utils::derive_private_revocation_key(&secp_ctx, &per_commitment_secret, &base_secret).unwrap(),
+                               SecretKey::from_slice(&secp_ctx, &hex_bytes("d09ffff62ddb2297ab000cc85bcb4283fdeb6aa052affbc9dddcf33b61078110").unwrap()[..]).unwrap());
+       }
+}
diff --git a/src/ln/channelmanager.rs b/src/ln/channelmanager.rs
new file mode 100644 (file)
index 0000000..3d78403
--- /dev/null
@@ -0,0 +1,1701 @@
+use bitcoin::blockdata::block::BlockHeader;
+use bitcoin::blockdata::transaction::Transaction;
+use bitcoin::blockdata::constants::genesis_block;
+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};
+use secp256k1::ecdh::SharedSecret;
+use secp256k1;
+
+use chain::chaininterface::{ChainListener,ChainWatchInterface,FeeEstimator};
+use ln::channel::Channel;
+use ln::channelmonitor::ManyChannelMonitor;
+use ln::router::Route;
+use ln::msgs;
+use ln::msgs::{HandleError,ChannelMessageHandler,MsgEncodable,MsgDecodable};
+use util::byte_utils;
+use util::events;
+use util::internal_traits;
+
+use rand::{thread_rng,Rng};
+
+use crypto::mac::{Mac,MacResult};
+use crypto::hmac::Hmac;
+use crypto::digest::Digest;
+use crypto::sha2::Sha256;
+use crypto::symmetriccipher::SynchronousStreamCipher;
+use crypto::chacha20::ChaCha20;
+
+use std::sync::{Mutex,Arc};
+use std::collections::HashMap;
+use std::collections::hash_map;
+use std::ptr;
+use std::mem;
+use std::time::{Instant,Duration};
+
+/// Stores the info we will need to send when we want to forward an HTLC onwards
+pub struct PendingForwardHTLCInfo {
+       onion_packet: Option<msgs::OnionPacket>,
+       payment_hash: [u8; 32],
+       short_channel_id: u64,
+       prev_short_channel_id: u64,
+       amt_to_forward: u64,
+       outgoing_cltv_value: u32,
+}
+
+struct ChannelHolder {
+       by_id: HashMap<Uint256, Channel>,
+       short_to_id: HashMap<u64, Uint256>,
+}
+
+/// We hold back HTLCs we intend to relay for a random interval in the range (this, 5*this). This
+/// provides some limited amount of privacy. Ideally this would range from somewhere like 1 second
+/// to 30 seconds, but people expect lightning to be, you know, kinda fast, sadly. We could
+/// probably increase this significantly.
+const MIN_HTLC_RELAY_HOLDING_CELL_MILLIS: u32 = 50;
+
+struct PendingForwardableHTLCs {
+       next_forward: Instant,
+       /// short channel id -> forward infos. Key of 0 means payments received
+       forward_htlcs: HashMap<u64, Vec<PendingForwardHTLCInfo>>,
+}
+
+/// Manager which keeps track of a number of channels and sends messages to the appropriate
+/// channel, also tracking HTLC preimages and forwarding onion packets appropriately.
+/// Implements ChannelMessageHandler, handling the multi-channel parts and passing things through
+/// to individual Channels.
+pub struct ChannelManager {
+       genesis_hash: Sha256dHash,
+       fee_estimator: Arc<FeeEstimator>,
+       monitor: Arc<ManyChannelMonitor>,
+       chain_monitor: Arc<ChainWatchInterface>,
+
+       announce_channels_publicly: bool,
+       fee_proportional_millionths: u32,
+       secp_ctx: Secp256k1,
+
+       channels: Mutex<ChannelHolder>,
+       our_network_key: SecretKey,
+
+       pending_events: Mutex<Vec<events::Event>>,
+       pending_htlcs_forwardable: Mutex<PendingForwardableHTLCs>,
+       pending_claimable_htlcs: Mutex<HashMap<[u8; 32], u64>>,
+}
+
+const CLTV_EXPIRY_DELTA: u16 = 6 * 24 * 2; //TODO?
+
+macro_rules! secp_call {
+       ( $res : expr ) => {
+               match $res {
+                       Ok(key) => key,
+                       //TODO: Make the err a parameter!
+                       Err(_) => return Err(HandleError{err: "Key error", msg: None})
+               }
+       };
+}
+
+struct OnionKeys {
+       #[cfg(test)]
+       shared_secret: SharedSecret,
+       #[cfg(test)]
+       blinding_factor: [u8; 32],
+       ephemeral_pubkey: PublicKey,
+       rho: [u8; 32],
+       mu: [u8; 32],
+}
+
+impl ChannelManager {
+       /// Constructs a new ChannelManager to hold several channels and route between them. This is
+       /// the main "logic hub" for all channel-related actions, and implements ChannelMessageHandler.
+       /// fee_proportional_millionths is an optional fee to charge any payments routed through us.
+       /// Non-proportional fees are fixed according to our risk using the provided fee estimator.
+       /// panics if channel_value_satoshis is >= (1 << 24)!
+       pub fn new(our_network_key: SecretKey, fee_proportional_millionths: u32, announce_channels_publicly: bool, network: Network, feeest: Arc<FeeEstimator>, monitor: Arc<ManyChannelMonitor>, chain_monitor: Arc<ChainWatchInterface>) -> Result<Arc<ChannelManager>, secp256k1::Error> {
+               let secp_ctx = Secp256k1::new();
+
+               let res = Arc::new(ChannelManager {
+                       genesis_hash: genesis_block(network).header.bitcoin_hash(),
+                       fee_estimator: feeest.clone(),
+                       monitor: monitor.clone(),
+                       chain_monitor: chain_monitor,
+
+                       announce_channels_publicly: announce_channels_publicly,
+                       fee_proportional_millionths: fee_proportional_millionths,
+                       secp_ctx: secp_ctx,
+
+                       channels: Mutex::new(ChannelHolder{by_id: HashMap::new(), short_to_id: HashMap::new()}),
+                       our_network_key: our_network_key,
+
+                       pending_events: Mutex::new(Vec::new()),
+                       pending_htlcs_forwardable: Mutex::new(PendingForwardableHTLCs {
+                               next_forward: Instant::now(),
+                               forward_htlcs: HashMap::new(),
+                       }),
+                       pending_claimable_htlcs: Mutex::new(HashMap::new()),
+               });
+               let weak_res = Arc::downgrade(&res);
+               res.chain_monitor.register_listener(weak_res);
+               Ok(res)
+       }
+
+       pub fn create_channel(&self, their_network_key: PublicKey, channel_value_satoshis: u64, user_id: u64) -> Result<msgs::OpenChannel, HandleError> {
+               let channel = Channel::new_outbound(&*self.fee_estimator, their_network_key, channel_value_satoshis, self.announce_channels_publicly, user_id);
+               let res = try!(channel.get_open_channel(self.genesis_hash.clone(), &*self.fee_estimator));
+               let mut channels = self.channels.lock().unwrap();
+               match channels.by_id.insert(channel.channel_id(), channel) {
+                       Some(_) => panic!("RNG is bad???"),
+                       None => Ok(res)
+               }
+       }
+
+       #[inline]
+       fn gen_rho_mu_from_shared_secret(shared_secret: &SharedSecret) -> ([u8; 32], [u8; 32]) {
+               ({
+                       let mut hmac = Hmac::new(Sha256::new(), &[0x72, 0x68, 0x6f]); // rho
+                       hmac.input(&shared_secret[..]);
+                       let mut res = [0; 32];
+                       hmac.raw_result(&mut res);
+                       res
+               },
+               {
+                       let mut hmac = Hmac::new(Sha256::new(), &[0x6d, 0x75]); // mu
+                       hmac.input(&shared_secret[..]);
+                       let mut res = [0; 32];
+                       hmac.raw_result(&mut res);
+                       res
+               })
+       }
+
+       #[inline]
+       fn gen_um_from_shared_secret(shared_secret: &SharedSecret) -> [u8; 32] {
+               let mut hmac = Hmac::new(Sha256::new(), &[0x75, 0x6d]); // um
+               hmac.input(&shared_secret[..]);
+               let mut res = [0; 32];
+               hmac.raw_result(&mut res);
+               res
+       }
+
+       fn gen_ammag_from_shared_secret(shared_secret: &SharedSecret) -> [u8; 32] {
+               let mut hmac = Hmac::new(Sha256::new(), &[0x61, 0x6d, 0x6d, 0x61, 0x67]); // ammag
+               hmac.input(&shared_secret[..]);
+               let mut res = [0; 32];
+               hmac.raw_result(&mut res);
+               res
+       }
+
+       fn construct_onion_keys(secp_ctx: &Secp256k1, route: &Route, session_priv: &SecretKey) -> Result<Vec<OnionKeys>, HandleError> {
+               let mut res = Vec::with_capacity(route.hops.len());
+               let mut blinded_priv = session_priv.clone();
+               let mut blinded_pub = secp_call!(PublicKey::from_secret_key(secp_ctx, &blinded_priv));
+               let mut first_iteration = true;
+
+               for hop in route.hops.iter() {
+                       let shared_secret = SharedSecret::new(secp_ctx, &hop.pubkey, &blinded_priv);
+
+                       let mut sha = Sha256::new();
+                       sha.input(&blinded_pub.serialize()[..]);
+                       sha.input(&shared_secret[..]);
+                       let mut blinding_factor = [0u8; 32];
+                       sha.result(&mut blinding_factor);
+
+                       if first_iteration {
+                               blinded_pub = secp_call!(PublicKey::from_secret_key(secp_ctx, &blinded_priv));
+                               first_iteration = false;
+                       }
+                       let ephemeral_pubkey = blinded_pub;
+
+                       secp_call!(blinded_priv.mul_assign(secp_ctx, &secp_call!(SecretKey::from_slice(secp_ctx, &blinding_factor))));
+                       blinded_pub = secp_call!(PublicKey::from_secret_key(secp_ctx, &blinded_priv));
+
+                       let (rho, mu) = ChannelManager::gen_rho_mu_from_shared_secret(&shared_secret);
+
+                       res.push(OnionKeys {
+                               #[cfg(test)]
+                               shared_secret: shared_secret,
+                               #[cfg(test)]
+                               blinding_factor: blinding_factor,
+                               ephemeral_pubkey: ephemeral_pubkey,
+                               rho: rho,
+                               mu: mu,
+                       });
+               }
+
+               Ok(res)
+       }
+
+       /// returns the hop data, as well as the first-hop value_msat and CLTV value we should send.
+       fn build_onion_payloads(route: &Route) -> Result<(Vec<msgs::OnionHopData>, u64, u32), HandleError> {
+               let mut cur_value_msat = 0u64;
+               let mut cur_cltv = 0u32;
+               let mut last_short_channel_id = 0;
+               let mut res: Vec<msgs::OnionHopData> = Vec::with_capacity(route.hops.len());
+               internal_traits::test_no_dealloc::<msgs::OnionHopData>(None);
+               unsafe { res.set_len(route.hops.len()); }
+
+               for (idx, hop) in route.hops.iter().enumerate().rev() {
+                       // First hop gets special values so that it can check, on receipt, that everything is
+                       // exactly as it should be (and the next hop isn't trying to probe to find out if we're
+                       // the intended recipient).
+                       let value_msat = if cur_value_msat == 0 { hop.fee_msat } else { cur_value_msat };
+                       let cltv = if cur_cltv == 0 { hop.cltv_expiry_delta } else { cur_cltv };
+                       res[idx] = msgs::OnionHopData {
+                               realm: 0,
+                               data: msgs::OnionRealm0HopData {
+                                       short_channel_id: last_short_channel_id,
+                                       amt_to_forward: value_msat,
+                                       outgoing_cltv_value: cltv,
+                               },
+                               hmac: [0; 32],
+                       };
+                       cur_value_msat += hop.fee_msat;
+                       if cur_value_msat >= 21000000 * 100000000 * 1000 {
+                               return Err(HandleError{err: "Channel fees overflowed?!", msg: None});
+                       }
+                       cur_cltv += hop.cltv_expiry_delta as u32;
+                       if cur_cltv >= 500000000 {
+                               return Err(HandleError{err: "Channel CLTV overflowed?!", msg: None});
+                       }
+                       last_short_channel_id = hop.short_channel_id;
+               }
+               Ok((res, cur_value_msat, cur_cltv))
+       }
+
+       #[inline]
+       fn shift_arr_right(arr: &mut [u8; 20*65]) {
+               unsafe {
+                       ptr::copy(arr[0..].as_ptr(), arr[65..].as_mut_ptr(), 19*65);
+               }
+               for i in 0..65 {
+                       arr[i] = 0;
+               }
+       }
+
+       #[inline]
+       fn xor_bufs(dst: &mut[u8], src: &[u8]) {
+               assert_eq!(dst.len(), src.len());
+
+               for i in 0..dst.len() {
+                       dst[i] ^= src[i];
+               }
+       }
+
+       const ZERO:[u8; 21*65] = [0; 21*65];
+       fn construct_onion_packet(mut payloads: Vec<msgs::OnionHopData>, onion_keys: Vec<OnionKeys>, associated_data: Vec<u8>) -> Result<msgs::OnionPacket, HandleError> {
+               let mut buf = Vec::with_capacity(21*65);
+               buf.resize(21*65, 0);
+
+               let filler = {
+                       let iters = payloads.len() - 1;
+                       let end_len = iters * 65;
+                       let mut res = Vec::with_capacity(end_len);
+                       res.resize(end_len, 0);
+
+                       for (i, keys) in onion_keys.iter().enumerate() {
+                               if i == payloads.len() - 1 { continue; }
+                               let mut chacha = ChaCha20::new(&keys.rho, &[0u8; 8]);
+                               chacha.process(&ChannelManager::ZERO, &mut buf); // We dont have a seek function :(
+                               ChannelManager::xor_bufs(&mut res[0..(i + 1)*65], &buf[(20 - i)*65..21*65]);
+                       }
+                       res
+               };
+
+               let mut packet_data = [0; 20*65];
+               let mut hmac_res = [0; 32];
+
+               for (i, (payload, keys)) in payloads.iter_mut().zip(onion_keys.iter()).rev().enumerate() {
+                       ChannelManager::shift_arr_right(&mut packet_data);
+                       payload.hmac = hmac_res;
+                       packet_data[0..65].copy_from_slice(&payload.encode()[..]);
+
+                       let mut chacha = ChaCha20::new(&keys.rho, &[0u8; 8]);
+                       chacha.process(&packet_data, &mut buf[0..20*65]);
+                       packet_data[..].copy_from_slice(&buf[0..20*65]);
+
+                       if i == 0 {
+                               packet_data[20*65 - filler.len()..20*65].copy_from_slice(&filler[..]);
+                       }
+
+                       let mut hmac = Hmac::new(Sha256::new(), &keys.mu);
+                       hmac.input(&packet_data);
+                       hmac.input(&associated_data[..]);
+                       hmac.raw_result(&mut hmac_res);
+               }
+
+               Ok(msgs::OnionPacket{
+                       version: 0,
+                       public_key: onion_keys.first().unwrap().ephemeral_pubkey,
+                       hop_data: packet_data,
+                       hmac: hmac_res,
+               })
+       }
+
+       /// Encrypts a failure packet. raw_packet can either be a
+       /// msgs::DecodedOnionErrorPacket.encode() result or a msgs::OnionErrorPacket.data element.
+       fn encrypt_failure_packet(shared_secret: &SharedSecret, raw_packet: &[u8]) -> msgs::OnionErrorPacket {
+               let ammag = ChannelManager::gen_ammag_from_shared_secret(&shared_secret);
+
+               let mut packet_crypted = Vec::with_capacity(raw_packet.len());
+               packet_crypted.resize(raw_packet.len(), 0);
+               let mut chacha = ChaCha20::new(&ammag, &[0u8; 8]);
+               chacha.process(&raw_packet, &mut packet_crypted[..]);
+               msgs::OnionErrorPacket {
+                       data: packet_crypted,
+               }
+       }
+
+       fn build_failure_packet(shared_secret: &SharedSecret, failure_type: u16, failure_data: &[u8]) -> msgs::DecodedOnionErrorPacket {
+               assert!(failure_data.len() <= 256 - 2);
+
+               let um = ChannelManager::gen_um_from_shared_secret(&shared_secret);
+
+               let failuremsg = {
+                       let mut res = Vec::with_capacity(2 + failure_data.len());
+                       res.push(((failure_type >> 8) & 0xff) as u8);
+                       res.push(((failure_type >> 0) & 0xff) as u8);
+                       res.extend_from_slice(&failure_data[..]);
+                       res
+               };
+               let pad = {
+                       let mut res = Vec::with_capacity(256 - 2 - failure_data.len());
+                       res.resize(256 - 2 - failure_data.len(), 0);
+                       res
+               };
+               let mut packet = msgs::DecodedOnionErrorPacket {
+                       hmac: [0; 32],
+                       failuremsg: failuremsg,
+                       pad: pad,
+               };
+
+               let mut hmac = Hmac::new(Sha256::new(), &um);
+               hmac.input(&packet.encode()[32..]);
+               hmac.raw_result(&mut packet.hmac);
+
+               packet
+       }
+
+       fn build_first_hop_failure_packet(shared_secret: &SharedSecret, failure_type: u16, failure_data: &[u8]) -> msgs::OnionErrorPacket {
+               let failure_packet = ChannelManager::build_failure_packet(shared_secret, failure_type, failure_data);
+               ChannelManager::encrypt_failure_packet(shared_secret, &failure_packet.encode()[..])
+       }
+
+       /// only fails if the channel does not yet have an assigned short_id
+       fn get_channel_update(&self, chan: &mut Channel) -> Result<msgs::ChannelUpdate, HandleError> {
+               let short_channel_id = match chan.get_short_channel_id() {
+                       None => return Err(HandleError{err: "Channel not yet established", msg: None}),
+                       Some(id) => id,
+               };
+
+               let were_node_one = PublicKey::from_secret_key(&self.secp_ctx, &self.our_network_key).unwrap().serialize()[..] < chan.get_their_node_id().serialize()[..];
+
+               let unsigned = msgs::UnsignedChannelUpdate {
+                       chain_hash: self.genesis_hash,
+                       short_channel_id: short_channel_id,
+                       timestamp: chan.get_channel_update_count(),
+                       flags: (!were_node_one) as u16 | ((!chan.is_live() as u16) << 1),
+                       cltv_expiry_delta: CLTV_EXPIRY_DELTA,
+                       htlc_minimum_msat: chan.get_our_htlc_minimum_msat(),
+                       fee_base_msat: chan.get_our_fee_base_msat(&*self.fee_estimator),
+                       fee_proportional_millionths: self.fee_proportional_millionths,
+               };
+
+               let msg_hash = Sha256dHash::from_data(&unsigned.encode()[..]);
+               let sig = self.secp_ctx.sign(&Message::from_slice(&msg_hash[..]).unwrap(), &self.our_network_key).unwrap(); //TODO Can we unwrap here?
+
+               Ok(msgs::ChannelUpdate {
+                       signature: sig,
+                       contents: unsigned
+               })
+       }
+
+       /// Sends a payment along a given route, returning the UpdateAddHTLC message to give to the
+       /// first hop in route. Value parameters are provided via the last hop in route, see
+       /// documentation for RouteHop fields for more info.
+       /// See-also docs on Channel::send_htlc_and_commit.
+       pub fn send_payment(&self, route: &Route, payment_hash: [u8; 32]) -> Result<Option<(msgs::UpdateAddHTLC, msgs::CommitmentSigned)>, HandleError> {
+               if route.hops.len() < 1 || route.hops.len() > 20 {
+                       return Err(HandleError{err: "Route didn't go anywhere/had bogus size", msg: None});
+               }
+
+               let mut rng = thread_rng();
+               let session_priv = secp_call!(SecretKey::from_slice(&self.secp_ctx, & {
+                       let mut session_key = [0; 32];
+                       rng.fill_bytes(&mut session_key);
+                       session_key
+               }));
+
+               let associated_data = Vec::new(); //TODO: What to put here?
+
+               let onion_keys = try!(ChannelManager::construct_onion_keys(&self.secp_ctx, route, &session_priv));
+               let (onion_payloads, htlc_msat, htlc_cltv) = try!(ChannelManager::build_onion_payloads(route));
+               let onion_packet = try!(ChannelManager::construct_onion_packet(onion_payloads, onion_keys, associated_data));
+
+               let mut channels = self.channels.lock().unwrap();
+               let id = match channels.short_to_id.get(&route.hops.first().unwrap().short_channel_id) {
+                       None => return Err(HandleError{err: "No channel available with first hop!", msg: None}),
+                       Some(id) => id.clone()
+               };
+               let chan = channels.by_id.get_mut(&id).unwrap();
+               if chan.get_their_node_id() != route.hops.first().unwrap().pubkey {
+                       return Err(HandleError{err: "Node ID mismatch on first hop!", msg: None});
+               }
+               chan.send_htlc_and_commit(htlc_msat, payment_hash, htlc_cltv, onion_packet)
+       }
+
+       /// 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: (Sha256dHash, u16)) {
+               let (chan, msg) = {
+                       let mut channels = self.channels.lock().unwrap();
+                       match channels.by_id.remove(&temporary_channel_id) {
+                               Some(mut chan) => {
+                                       match chan.get_outbound_funding_created(funding_txo.0, funding_txo.1) {
+                                               Ok(funding_msg) => {
+                                                       (chan, funding_msg)
+                                               },
+                                               Err(_e) => {
+                                                       //TODO: Push e to pendingevents
+                                                       return;
+                                               }
+                                       }
+                               },
+                               None => return
+                       }
+               }; // Release channel lock for install_watch_outpoint call,
+               let chan_monitor = chan.channel_monitor();
+               match self.monitor.add_update_monitor(chan_monitor.get_funding_txo().unwrap(), chan_monitor) {
+                       Ok(()) => {},
+                       Err(_e) => {
+                               //TODO: Push e to pendingevents?
+                               return;
+                       }
+               };
+
+               {
+                       let mut pending_events = self.pending_events.lock().unwrap();
+                       pending_events.push(events::Event::SendFundingCreated {
+                               node_id: chan.get_their_node_id(),
+                               msg: msg,
+                       });
+               }
+
+               let mut channels = self.channels.lock().unwrap();
+               channels.by_id.insert(chan.channel_id(), chan);
+       }
+
+       fn get_announcement_sigs(&self, chan: &Channel) -> Result<Option<msgs::AnnouncementSignatures>, HandleError> {
+               if !chan.is_usable() { return Ok(None) }
+
+               let (announcement, our_bitcoin_sig) = try!(chan.get_channel_announcement(self.get_our_node_id(), self.genesis_hash.clone()));
+               let msghash = Message::from_slice(&Sha256dHash::from_data(&announcement.encode()[..])[..]).unwrap();
+               let our_node_sig = secp_call!(self.secp_ctx.sign(&msghash, &self.our_network_key));
+
+               Ok(Some(msgs::AnnouncementSignatures {
+                       channel_id: chan.channel_id(),
+                       short_channel_id: chan.get_short_channel_id().unwrap(),
+                       node_signature: our_node_sig,
+                       bitcoin_signature: our_bitcoin_sig,
+               }))
+       }
+
+       pub fn process_pending_htlc_forward(&self) {
+               let forward_htlcs = {
+                       let mut pending_forwards = self.pending_htlcs_forwardable.lock().unwrap();
+                       if Instant::now() < pending_forwards.next_forward {
+                               return;
+                       }
+                       let mut new_map = HashMap::new();
+                       mem::swap(&mut new_map, &mut pending_forwards.forward_htlcs);
+                       new_map
+               };
+
+               let mut new_events = Vec::new();
+
+               {
+                       for (short_chan_id, pending_forwards) in forward_htlcs.iter() {
+                               let mut pending_claimable_htlcs = self.pending_claimable_htlcs.lock().unwrap();
+                               for forward_info in pending_forwards {
+                                       pending_claimable_htlcs.insert(forward_info.payment_hash, forward_info.prev_short_channel_id);
+                                       if *short_chan_id == 0 {
+                                               new_events.push(events::Event::PaymentReceived {
+                                                       payment_hash: forward_info.payment_hash,
+                                                       amt: forward_info.amt_to_forward,
+                                               });
+                                       }
+                               }
+                       }
+               }
+               {
+                       let mut channels = self.channels.lock().unwrap();
+                       for (short_chan_id, pending_forwards) in forward_htlcs {
+                               if short_chan_id != 0 {
+                                       let forward_chan_id = match channels.short_to_id.get(&short_chan_id) {
+                                               Some(chan_id) => chan_id.clone(),
+                                               None => {
+                                                       // TODO: Send a failure packet back on each pending_forward
+                                                       continue;
+                                               }
+                                       };
+                                       let forward_chan = &mut channels.by_id.get_mut(&forward_chan_id).unwrap();
+
+                                       let mut add_htlc_msgs = Vec::new();
+                                       for forward_info in pending_forwards {
+                                               match forward_chan.send_htlc(forward_info.amt_to_forward, forward_info.payment_hash, forward_info.outgoing_cltv_value, forward_info.onion_packet.unwrap()) {
+                                                       Err(_e) => {
+                                                               // TODO: Send a failure packet back
+                                                               continue;
+                                                       },
+                                                       Ok(update_add) => {
+                                                               match update_add {
+                                                                       Some(msg) => { add_htlc_msgs.push(msg); },
+                                                                       None => {
+                                                                               // Nothing to do here...we're waiting on a remote
+                                                                               // revoke_and_ack before we can add anymore HTLCs. The Channel
+                                                                               // will automatically handle building the update_add_htlc and
+                                                                               // commitment_signed messages when we can.
+                                                                               // TODO: Do some kind of timer to set the channel as !is_live()
+                                                                               // as we dont really want others relying on us relaying through
+                                                                               // this channel currently :/.
+                                                                       }
+                                                               }
+                                                       }
+                                               }
+                                       }
+
+                                       if !add_htlc_msgs.is_empty() {
+                                               let commitment_msg = match forward_chan.send_commitment() {
+                                                       Ok(msg) => msg,
+                                                       Err(_) => {
+                                                               //TODO: Handle...this is bad!
+                                                               continue;
+                                                       },
+                                               };
+                                               new_events.push(events::Event::SendHTLCs {
+                                                       node_id: forward_chan.get_their_node_id(),
+                                                       msgs: add_htlc_msgs,
+                                                       commitment_msg: commitment_msg,
+                                               });
+                                       }
+                               }
+                       }
+               }
+
+               if new_events.is_empty() { return }
+
+               let mut events = self.pending_events.lock().unwrap();
+               events.reserve(new_events.len());
+               for event in new_events.drain(..) {
+                       events.push(event);
+               }
+       }
+
+       /// Provides a payment preimage in response to a PaymentReceived event, returning true and
+       /// generating message events for the net layer to claim the payment, if possible. Thus, you
+       /// should probably kick the net layer to go send messages if this returns true!
+       pub fn claim_funds(&self, payment_preimage: [u8; 32]) -> bool {
+               let mut sha = Sha256::new();
+               sha.input(&payment_preimage);
+               let mut payment_hash = [0; 32];
+               sha.result(&mut payment_hash);
+
+               let short_chan_id = {
+                       let mut pending_claimable_htlcs = self.pending_claimable_htlcs.lock().unwrap();
+                       match pending_claimable_htlcs.remove(&payment_hash) {
+                               Some(short_id) => short_id,
+                               None => return false,
+                       }
+               };
+
+               let (node_id, fulfill_msg) = {
+                       let mut channels = self.channels.lock().unwrap();
+                       let chan_id = match channels.short_to_id.get(&short_chan_id) {
+                               Some(chan_id) => chan_id.clone(),
+                               None => return false
+                       };
+
+                       let chan = channels.by_id.get_mut(&chan_id).unwrap();
+                       match chan.get_update_fulfill_htlc(payment_preimage) {
+                               Ok(msg) => (chan.get_their_node_id(), msg),
+                               Err(_e) => {
+                                       //TODO: Do something with e?
+                                       return false;
+                               },
+                       }
+               };
+
+               let mut pending_events = self.pending_events.lock().unwrap();
+               pending_events.push(events::Event::SendFulfillHTLC {
+                       node_id: node_id,
+                       msg: fulfill_msg
+               });
+
+               true
+       }
+
+       /// Gets the node_id held by this ChannelManager
+       pub fn get_our_node_id(&self) -> PublicKey {
+               PublicKey::from_secret_key(&self.secp_ctx, &self.our_network_key).unwrap()
+       }
+}
+
+impl events::EventsProvider for ChannelManager {
+       fn get_and_clear_pending_events(&self) -> Vec<events::Event> {
+               let mut pending_events = self.pending_events.lock().unwrap();
+               let mut ret = Vec::new();
+               mem::swap(&mut ret, &mut *pending_events);
+               ret
+       }
+}
+
+impl ChainListener for ChannelManager {
+       fn block_connected(&self, header: &BlockHeader, height: u32, txn_matched: &[&Transaction], indexes_of_txn_matched: &[u32]) {
+               let mut new_funding_locked_messages = Vec::new();
+               {
+                       let mut channels = self.channels.lock().unwrap();
+                       let mut short_to_ids_to_insert = Vec::new();
+                       for channel in channels.by_id.values_mut() {
+                               match channel.block_connected(header, height, txn_matched, indexes_of_txn_matched) {
+                                       Some(funding_locked) => {
+                                               let announcement_sigs = match self.get_announcement_sigs(channel) {
+                                                       Ok(res) => res,
+                                                       Err(_e) => {
+                                                               //TODO: push e on events and blow up the channel (it has bad keys)
+                                                               continue;
+                                                       }
+                                               };
+                                               new_funding_locked_messages.push(events::Event::SendFundingLocked {
+                                                       node_id: channel.get_their_node_id(),
+                                                       msg: funding_locked,
+                                                       announcement_sigs: announcement_sigs
+                                               });
+                                               short_to_ids_to_insert.push((channel.get_short_channel_id().unwrap(), channel.channel_id()));
+                                       },
+                                       None => {}
+                               }
+                       }
+                       for to_insert in short_to_ids_to_insert {
+                               channels.short_to_id.insert(to_insert.0, to_insert.1);
+                       }
+               }
+               let mut pending_events = self.pending_events.lock().unwrap();
+               for funding_locked in new_funding_locked_messages.drain(..) {
+                       pending_events.push(funding_locked);
+               }
+       }
+
+       fn block_disconnected(&self, header: &BlockHeader) {
+               let mut channels = self.channels.lock().unwrap();
+               for channel in channels.by_id.values_mut() {
+                       if channel.block_disconnected(header) {
+                               //TODO Close channel here
+                       }
+               }
+       }
+}
+
+impl ChannelMessageHandler for ChannelManager {
+       //TODO: Handle errors and close channel (or so)
+       fn handle_open_channel(&self, their_node_id: &PublicKey, msg: &msgs::OpenChannel) -> Result<msgs::AcceptChannel, HandleError> {
+               if msg.chain_hash != self.genesis_hash {
+                       return Err(HandleError{err: "Unknown genesis block hash", msg: None});
+               }
+               let mut channels = self.channels.lock().unwrap();
+               if channels.by_id.contains_key(&msg.temporary_channel_id) {
+                       return Err(HandleError{err: "temporary_channel_id collision!", msg: None});
+               }
+               let channel = try!(Channel::new_from_req(&*self.fee_estimator, their_node_id.clone(), msg, 0, self.announce_channels_publicly));
+               let accept_msg = try!(channel.get_accept_channel());
+               channels.by_id.insert(channel.channel_id(), channel);
+               Ok(accept_msg)
+       }
+
+       fn handle_accept_channel(&self, their_node_id: &PublicKey, msg: &msgs::AcceptChannel) -> Result<(), HandleError> {
+               let (value, output_script, user_id) = {
+                       let mut channels = self.channels.lock().unwrap();
+                       match channels.by_id.get_mut(&msg.temporary_channel_id) {
+                               Some(chan) => {
+                                       if chan.get_their_node_id() != *their_node_id {
+                                               return Err(HandleError{err: "Got a message for a channel from the wrong node!", msg: None})
+                                       }
+                                       try!(chan.accept_channel(&msg));
+                                       (chan.get_value_satoshis(), chan.get_funding_redeemscript().to_v0_p2wsh(), chan.get_user_id())
+                               },
+                               None => return Err(HandleError{err: "Failed to find corresponding channel", msg: None})
+                       }
+               };
+               let mut pending_events = self.pending_events.lock().unwrap();
+               pending_events.push(events::Event::FundingGenerationReady {
+                       temporary_channel_id: msg.temporary_channel_id,
+                       channel_value_satoshis: value,
+                       output_script: output_script,
+                       user_channel_id: user_id,
+               });
+               Ok(())
+       }
+
+       fn handle_funding_created(&self, their_node_id: &PublicKey, msg: &msgs::FundingCreated) -> Result<msgs::FundingSigned, HandleError> {
+               //TODO: broke this - a node shouldnt be able to get their channel removed by sending a
+               //funding_created a second time, or long after the first, or whatever (note this also
+               //leaves the short_to_id map in a busted state.
+               let chan = {
+                       let mut channels = self.channels.lock().unwrap();
+                       match channels.by_id.remove(&msg.temporary_channel_id) {
+                               Some(mut chan) => {
+                                       if chan.get_their_node_id() != *their_node_id {
+                                               return Err(HandleError{err: "Got a message for a channel from the wrong node!", msg: None})
+                                       }
+                                       match chan.funding_created(msg) {
+                                               Ok(funding_msg) => {
+                                                       (chan, funding_msg)
+                                               },
+                                               Err(e) => {
+                                                       return Err(e);
+                                               }
+                                       }
+                               },
+                               None => return Err(HandleError{err: "Failed to find corresponding channel", msg: None})
+                       }
+               }; // Release channel lock for install_watch_outpoint call,
+                  // note that this means if the remote end is misbehaving and sends a message for the same
+                  // channel back-to-back with funding_created, we'll end up thinking they sent a message
+                  // for a bogus channel.
+               let chan_monitor = chan.0.channel_monitor();
+               try!(self.monitor.add_update_monitor(chan_monitor.get_funding_txo().unwrap(), chan_monitor));
+               let mut channels = self.channels.lock().unwrap();
+               channels.by_id.insert(chan.1.channel_id, chan.0);
+               Ok(chan.1)
+       }
+
+       fn handle_funding_signed(&self, their_node_id: &PublicKey, msg: &msgs::FundingSigned) -> Result<(), HandleError> {
+               let (funding_txo, user_id) = {
+                       let mut channels = self.channels.lock().unwrap();
+                       match channels.by_id.get_mut(&msg.channel_id) {
+                               Some(chan) => {
+                                       if chan.get_their_node_id() != *their_node_id {
+                                               return Err(HandleError{err: "Got a message for a channel from the wrong node!", msg: None})
+                                       }
+                                       try!(chan.funding_signed(&msg));
+                                       (chan.get_funding_txo().unwrap(), chan.get_user_id())
+                               },
+                               None => return Err(HandleError{err: "Failed to find corresponding channel", msg: None})
+                       }
+               };
+               let mut pending_events = self.pending_events.lock().unwrap();
+               pending_events.push(events::Event::FundingBroadcastSafe {
+                       funding_txo: funding_txo,
+                       user_channel_id: user_id,
+               });
+               Ok(())
+       }
+
+       fn handle_funding_locked(&self, their_node_id: &PublicKey, msg: &msgs::FundingLocked) -> Result<Option<msgs::AnnouncementSignatures>, HandleError> {
+               let mut channels = self.channels.lock().unwrap();
+               match channels.by_id.get_mut(&msg.channel_id) {
+                       Some(chan) => {
+                               if chan.get_their_node_id() != *their_node_id {
+                                       return Err(HandleError{err: "Got a message for a channel from the wrong node!", msg: None})
+                               }
+                               try!(chan.funding_locked(&msg));
+                               return Ok(try!(self.get_announcement_sigs(chan)));
+                       },
+                       None => return Err(HandleError{err: "Failed to find corresponding channel", msg: None})
+               };
+       }
+
+       fn handle_shutdown(&self, _their_node_id: &PublicKey, _msg: &msgs::Shutdown) -> Result<(), HandleError> {
+               unimplemented!()
+       }
+
+       fn handle_closing_signed(&self, _their_node_id: &PublicKey, _msg: &msgs::ClosingSigned) -> Result<(), HandleError> {
+               unimplemented!()
+       }
+
+       fn handle_update_add_htlc(&self, their_node_id: &PublicKey, msg: &msgs::UpdateAddHTLC) -> Result<(), msgs::HandleError> {
+               //TODO: BOLT 4 points out a specific attack where a peer may re-send a onion packet and
+               //determine the state of the payment based on our response/if we forward anything/the time
+               //we take to respond. We should take care to avoid allowing such an attack.
+               //
+               //TODO: There exists a further attack where a node may garble the onion data, forward it to
+               //us repeatedly garbled in different ways, and compare our error messages, which are
+               //encrypted with the same key. Its not immediately obvious how to usefully exploit that,
+               //but we should prevent it anyway.
+
+               let shared_secret = SharedSecret::new(&self.secp_ctx, &msg.onion_routing_packet.public_key, &self.our_network_key);
+               let (rho, mu) = ChannelManager::gen_rho_mu_from_shared_secret(&shared_secret);
+
+               let associated_data = Vec::new(); //TODO: What to put here?
+
+               if msg.onion_routing_packet.version != 0 {
+                       //TODO: Spec doesnt indicate if we should only hash hop_data here (and in other
+                       //sha256_of_onion error data packets), or the entire onion_routing_packet. Either way,
+                       //the hash doesn't really serve any purpuse - in the case of hashing all data, the
+                       //receiving node would have to brute force to figure out which version was put in the
+                       //packet by the node that send us the message, in the case of hashing the hop_data, the
+                       //node knows the HMAC matched, so they already know what is there...
+                       let mut sha = Sha256::new();
+                       sha.input(&msg.onion_routing_packet.hop_data);
+                       let mut onion_hash = [0; 32];
+                       sha.result(&mut onion_hash);
+                       return Err(msgs::HandleError {
+                               err: "Unknown onion packet version",
+                               msg: Some(msgs::ErrorMessage::UpdateFailHTLC {
+                                       msg: msgs::UpdateFailHTLC {
+                                               channel_id: msg.channel_id,
+                                               htlc_id: msg.htlc_id,
+                                               reason: ChannelManager::build_first_hop_failure_packet(&shared_secret, 0x8000 | 0x4000 | 4, &onion_hash),
+                                       }
+                               }),
+                       });
+               }
+
+               let mut hmac = Hmac::new(Sha256::new(), &mu);
+               hmac.input(&msg.onion_routing_packet.hop_data);
+               hmac.input(&associated_data[..]);
+               if hmac.result() != MacResult::new(&msg.onion_routing_packet.hmac) {
+                       let mut sha = Sha256::new();
+                       sha.input(&msg.onion_routing_packet.hop_data);
+                       let mut onion_hash = [0; 32];
+                       sha.result(&mut onion_hash);
+                       return Err(HandleError{err: "HMAC Check failed",
+                               msg: Some(msgs::ErrorMessage::UpdateFailHTLC {
+                                       msg: msgs::UpdateFailHTLC {
+                                               channel_id: msg.channel_id,
+                                               htlc_id: msg.htlc_id,
+                                               reason: ChannelManager::build_first_hop_failure_packet(&shared_secret, 0x8000 | 0x4000 | 5, &onion_hash),
+                                       }
+                               }),
+                       });
+               }
+
+               let mut chacha = ChaCha20::new(&rho, &[0u8; 8]);
+               let next_hop_data = {
+                       let mut decoded = [0; 65];
+                       chacha.process(&msg.onion_routing_packet.hop_data[0..65], &mut decoded);
+                       match msgs::OnionHopData::decode(&decoded[..]) {
+                               Err(err) => {
+                                       let error_code = match err {
+                                               msgs::DecodeError::UnknownRealmByte => 0x4000 | 1,
+                                               _ => 0x2000 | 2, // Should never happen
+                                       };
+                                       return Err(HandleError{err: "Unable to decode our hop data",
+                                               msg: Some(msgs::ErrorMessage::UpdateFailHTLC {
+                                                       msg: msgs::UpdateFailHTLC {
+                                                               channel_id: msg.channel_id,
+                                                               htlc_id: msg.htlc_id,
+                                                               reason: ChannelManager::build_first_hop_failure_packet(&shared_secret, error_code, &[0;0]),
+                                                       }
+                                               }),
+                                       });
+                               },
+                               Ok(msg) => msg
+                       }
+               };
+
+               let mut pending_forward_info = if next_hop_data.hmac == [0; 32] {
+                               // OUR PAYMENT!
+                               if next_hop_data.data.amt_to_forward != msg.amount_msat {
+                                       return Err(HandleError{err: "Upstream node sent less than we were supposed to receive in payment",
+                                               msg: Some(msgs::ErrorMessage::UpdateFailHTLC {
+                                                       msg: msgs::UpdateFailHTLC {
+                                                               channel_id: msg.channel_id,
+                                                               htlc_id: msg.htlc_id,
+                                                               reason: ChannelManager::build_first_hop_failure_packet(&shared_secret, 19, &byte_utils::be64_to_array(msg.amount_msat)),
+                                                       }
+                                               }),
+                                       });
+                               }
+                               if next_hop_data.data.outgoing_cltv_value != msg.cltv_expiry {
+                                       return Err(HandleError{err: "Upstream node set CLTV to the wrong value",
+                                               msg: Some(msgs::ErrorMessage::UpdateFailHTLC {
+                                                       msg: msgs::UpdateFailHTLC {
+                                                               channel_id: msg.channel_id,
+                                                               htlc_id: msg.htlc_id,
+                                                               reason: ChannelManager::build_first_hop_failure_packet(&shared_secret, 18, &byte_utils::be32_to_array(msg.cltv_expiry)),
+                                                       }
+                                               }),
+                                       });
+                               }
+
+                               // Note that we could obviously respond immediately with a update_fulfill_htlc
+                               // message, however that would leak that we are the recipient of this payment, so
+                               // instead we stay symmetric with the forwarding case, only responding (after a
+                               // delay) once they've send us a commitment_signed!
+
+                               PendingForwardHTLCInfo {
+                                       onion_packet: None,
+                                       payment_hash: msg.payment_hash.clone(),
+                                       short_channel_id: 0,
+                                       prev_short_channel_id: 0,
+                                       amt_to_forward: next_hop_data.data.amt_to_forward,
+                                       outgoing_cltv_value: next_hop_data.data.outgoing_cltv_value,
+                               }
+                       } else {
+                               let mut new_packet_data = [0; 20*65];
+                               chacha.process(&msg.onion_routing_packet.hop_data[65..], &mut new_packet_data[0..19*65]);
+                               chacha.process(&ChannelManager::ZERO[0..65], &mut new_packet_data[19*65..]);
+
+                               let mut new_pubkey = msg.onion_routing_packet.public_key.clone();
+
+                               let blinding_factor = {
+                                       let mut sha = Sha256::new();
+                                       sha.input(&new_pubkey.serialize()[..]);
+                                       sha.input(&shared_secret[..]);
+                                       let mut res = [0u8; 32];
+                                       sha.result(&mut res);
+                                       match SecretKey::from_slice(&self.secp_ctx, &res) {
+                                               Err(_) => {
+                                                       // Return temporary node failure as its technically our issue, not the
+                                                       // channel's issue.
+                                                       return Err(HandleError{err: "Blinding factor is an invalid private key",
+                                                               msg: Some(msgs::ErrorMessage::UpdateFailHTLC {
+                                                                       msg: msgs::UpdateFailHTLC {
+                                                                               channel_id: msg.channel_id,
+                                                                               htlc_id: msg.htlc_id,
+                                                                               reason: ChannelManager::build_first_hop_failure_packet(&shared_secret, 0x2000 | 2, &[0;0]),
+                                                                       }
+                                                               }),
+                                                       });
+                                               },
+                                               Ok(key) => key
+                                       }
+                               };
+
+                               match new_pubkey.mul_assign(&self.secp_ctx, &blinding_factor) {
+                                       Err(_) => {
+                                               // Return temporary node failure as its technically our issue, not the
+                                               // channel's issue.
+                                               return Err(HandleError{err: "New blinding factor is an invalid private key",
+                                                       msg: Some(msgs::ErrorMessage::UpdateFailHTLC {
+                                                               msg: msgs::UpdateFailHTLC {
+                                                                       channel_id: msg.channel_id,
+                                                                       htlc_id: msg.htlc_id,
+                                                                       reason: ChannelManager::build_first_hop_failure_packet(&shared_secret, 0x2000 | 2, &[0;0]),
+                                                               }
+                                                       }),
+                                               });
+                                       },
+                                       Ok(_) => {}
+                               };
+
+                               let outgoing_packet = msgs::OnionPacket {
+                                       version: 0,
+                                       public_key: new_pubkey,
+                                       hop_data: new_packet_data,
+                                       hmac: next_hop_data.hmac.clone(),
+                               };
+
+                               //TODO: Check amt_to_forward and outgoing_cltv_value are within acceptable ranges!
+
+                               PendingForwardHTLCInfo {
+                                       onion_packet: Some(outgoing_packet),
+                                       payment_hash: msg.payment_hash.clone(),
+                                       short_channel_id: next_hop_data.data.short_channel_id,
+                                       prev_short_channel_id: 0,
+                                       amt_to_forward: next_hop_data.data.amt_to_forward,
+                                       outgoing_cltv_value: next_hop_data.data.outgoing_cltv_value,
+                               }
+                       };
+
+               let mut channels = self.channels.lock().unwrap();
+
+               if pending_forward_info.short_channel_id != 0 {
+                       let forwarding_id = match channels.short_to_id.get(&pending_forward_info.short_channel_id) {
+                               None => {
+                                       return Err(HandleError{err: "Don't have available channel for forwarding as requested.",
+                                               msg: Some(msgs::ErrorMessage::UpdateFailHTLC {
+                                                       msg: msgs::UpdateFailHTLC {
+                                                               channel_id: msg.channel_id,
+                                                               htlc_id: msg.htlc_id,
+                                                               reason: ChannelManager::build_first_hop_failure_packet(&shared_secret, 0x4000 | 10, &[0;0]),
+                                                       }
+                                               }),
+                                       });
+                               },
+                               Some(id) => id.clone(),
+                       };
+                       let chan = channels.by_id.get_mut(&forwarding_id).unwrap();
+                       if !chan.is_live() {
+                               let chan_update = self.get_channel_update(chan).unwrap();
+                               return Err(HandleError{err: "Forwarding channel is not in a ready state.",
+                                       msg: Some(msgs::ErrorMessage::UpdateFailHTLC {
+                                               msg: msgs::UpdateFailHTLC {
+                                                       channel_id: msg.channel_id,
+                                                       htlc_id: msg.htlc_id,
+                                                       reason: ChannelManager::build_first_hop_failure_packet(&shared_secret, 0x4000 | 10, &chan_update.encode()[..]),
+                                               }
+                                       }),
+                               });
+                       }
+               }
+
+               match channels.by_id.get_mut(&msg.channel_id) {
+                       Some(chan) => {
+                               if chan.get_their_node_id() != *their_node_id {
+                                       return Err(HandleError{err: "Got a message for a channel from the wrong node!", msg: None})
+                               }
+                               if !chan.is_usable() {
+                                       return Err(HandleError{err: "Channel not yet available for receiving HTLCs", msg: None});
+                               }
+                               pending_forward_info.prev_short_channel_id = chan.get_short_channel_id().unwrap();
+                               chan.update_add_htlc(&msg, pending_forward_info)
+                       },
+                       None => return Err(HandleError{err: "Failed to find corresponding channel", msg: None}), //TODO: panic?
+               }
+       }
+
+       fn handle_update_fulfill_htlc(&self, their_node_id: &PublicKey, msg: &msgs::UpdateFulfillHTLC) -> Result<Option<(Vec<msgs::UpdateAddHTLC>, msgs::CommitmentSigned)>, HandleError> {
+               let res = {
+                       let mut channels = self.channels.lock().unwrap();
+                       match channels.by_id.get_mut(&msg.channel_id) {
+                               Some(chan) => {
+                                       if chan.get_their_node_id() != *their_node_id {
+                                               return Err(HandleError{err: "Got a message for a channel from the wrong node!", msg: None})
+                                       }
+                                       chan.update_fulfill_htlc(&msg)
+                               },
+                               None => return Err(HandleError{err: "Failed to find corresponding channel", msg: None})
+                       }
+               };
+               //TODO: Delay the claimed_funds relaying just like we do outbound relay!
+               self.claim_funds(msg.payment_preimage.clone());
+               res
+       }
+
+       fn handle_update_fail_htlc(&self, their_node_id: &PublicKey, msg: &msgs::UpdateFailHTLC) -> Result<Option<(Vec<msgs::UpdateAddHTLC>, msgs::CommitmentSigned)>, HandleError> {
+               let mut channels = self.channels.lock().unwrap();
+               match channels.by_id.get_mut(&msg.channel_id) {
+                       Some(chan) => {
+                               if chan.get_their_node_id() != *their_node_id {
+                                       return Err(HandleError{err: "Got a message for a channel from the wrong node!", msg: None})
+                               }
+                               chan.update_fail_htlc(&msg)
+                       },
+                       None => return Err(HandleError{err: "Failed to find corresponding channel", msg: None})
+               }
+               //TODO Pass the reason backwards through the onion channel
+       }
+
+       fn handle_update_fail_malformed_htlc(&self, their_node_id: &PublicKey, msg: &msgs::UpdateFailMalformedHTLC) -> Result<Option<(Vec<msgs::UpdateAddHTLC>, msgs::CommitmentSigned)>, HandleError> {
+               let mut channels = self.channels.lock().unwrap();
+               match channels.by_id.get_mut(&msg.channel_id) {
+                       Some(chan) => {
+                               if chan.get_their_node_id() != *their_node_id {
+                                       return Err(HandleError{err: "Got a message for a channel from the wrong node!", msg: None})
+                               }
+                               chan.update_fail_malformed_htlc(&msg)
+                       },
+                       None => return Err(HandleError{err: "Failed to find corresponding channel", msg: None})
+               }
+       }
+
+       fn handle_commitment_signed(&self, their_node_id: &PublicKey, msg: &msgs::CommitmentSigned) -> Result<msgs::RevokeAndACK, HandleError> {
+               let ((res, mut forwarding_infos), monitor) = {
+                       let mut channels = self.channels.lock().unwrap();
+                       match channels.by_id.get_mut(&msg.channel_id) {
+                               Some(chan) => {
+                                       if chan.get_their_node_id() != *their_node_id {
+                                               return Err(HandleError{err: "Got a message for a channel from the wrong node!", msg: None})
+                                       }
+                                       (try!(chan.commitment_signed(&msg)), chan.channel_monitor())
+                               },
+                               None => return Err(HandleError{err: "Failed to find corresponding channel", msg: None})
+                       }
+               };
+               //TODO: Only if we store HTLC sigs
+               try!(self.monitor.add_update_monitor(monitor.get_funding_txo().unwrap(), monitor));
+
+               let mut forward_event = None;
+               {
+                       let mut pending_htlcs = self.pending_htlcs_forwardable.lock().unwrap();
+                       if pending_htlcs.forward_htlcs.is_empty() {
+                               let mut rng = thread_rng();
+                               forward_event = Some(Instant::now() + Duration::from_millis(((rng.next_f32() * 4.0 + 1.0) * MIN_HTLC_RELAY_HOLDING_CELL_MILLIS as f32) as u64));
+                               pending_htlcs.next_forward = forward_event.unwrap();
+                       }
+                       for forward_info in forwarding_infos.drain(..) {
+                               match pending_htlcs.forward_htlcs.entry(forward_info.short_channel_id) {
+                                       hash_map::Entry::Occupied(mut entry) => {
+                                               entry.get_mut().push(forward_info);
+                                       },
+                                       hash_map::Entry::Vacant(entry) => {
+                                               entry.insert(vec!(forward_info));
+                                       }
+                               }
+                       }
+               }
+               match forward_event {
+                       Some(time) => {
+                               let mut pending_events = self.pending_events.lock().unwrap();
+                               pending_events.push(events::Event::PendingHTLCsForwardable {
+                                       time_forwardable: time
+                               });
+                       }
+                       None => {},
+               }
+
+               Ok(res)
+       }
+
+       fn handle_revoke_and_ack(&self, their_node_id: &PublicKey, msg: &msgs::RevokeAndACK) -> Result<(), HandleError> {
+               let monitor = {
+                       let mut channels = self.channels.lock().unwrap();
+                       match channels.by_id.get_mut(&msg.channel_id) {
+                               Some(chan) => {
+                                       if chan.get_their_node_id() != *their_node_id {
+                                               return Err(HandleError{err: "Got a message for a channel from the wrong node!", msg: None})
+                                       }
+                                       try!(chan.revoke_and_ack(&msg));
+                                       chan.channel_monitor()
+                               },
+                               None => return Err(HandleError{err: "Failed to find corresponding channel", msg: None})
+                       }
+               };
+               try!(self.monitor.add_update_monitor(monitor.get_funding_txo().unwrap(), monitor));
+               Ok(())
+       }
+
+       fn handle_update_fee(&self, their_node_id: &PublicKey, msg: &msgs::UpdateFee) -> Result<(), HandleError> {
+               let mut channels = self.channels.lock().unwrap();
+               match channels.by_id.get_mut(&msg.channel_id) {
+                       Some(chan) => {
+                               if chan.get_their_node_id() != *their_node_id {
+                                       return Err(HandleError{err: "Got a message for a channel from the wrong node!", msg: None})
+                               }
+                               chan.update_fee(&*self.fee_estimator, &msg)
+                       },
+                       None => return Err(HandleError{err: "Failed to find corresponding channel", msg: None})
+               }
+       }
+
+       fn handle_announcement_signatures(&self, their_node_id: &PublicKey, msg: &msgs::AnnouncementSignatures) -> Result<(), HandleError> {
+               let (chan_announcement, chan_update) = {
+                       let mut channels = self.channels.lock().unwrap();
+                       match channels.by_id.get_mut(&msg.channel_id) {
+                               Some(chan) => {
+                                       if chan.get_their_node_id() != *their_node_id {
+                                               return Err(HandleError{err: "Got a message for a channel from the wrong node!", msg: None})
+                                       }
+                                       if !chan.is_usable() {
+                                               return Err(HandleError{err: "Got an announcement_signatures before we were ready for it", msg: None });
+                                       }
+
+                                       let our_node_id = self.get_our_node_id();
+                                       let (announcement, our_bitcoin_sig) = try!(chan.get_channel_announcement(our_node_id.clone(), self.genesis_hash.clone()));
+
+                                       let were_node_one = announcement.node_id_1 == our_node_id;
+                                       let msghash = Message::from_slice(&Sha256dHash::from_data(&announcement.encode()[..])[..]).unwrap();
+                                       secp_call!(self.secp_ctx.verify(&msghash, &msg.node_signature, if were_node_one { &announcement.node_id_2 } else { &announcement.node_id_1 }));
+                                       secp_call!(self.secp_ctx.verify(&msghash, &msg.bitcoin_signature, if were_node_one { &announcement.bitcoin_key_2 } else { &announcement.bitcoin_key_1 }));
+
+                                       let our_node_sig = secp_call!(self.secp_ctx.sign(&msghash, &self.our_network_key));
+
+                                       (msgs::ChannelAnnouncement {
+                                               node_signature_1: if were_node_one { our_node_sig } else { msg.node_signature },
+                                               node_signature_2: if were_node_one { msg.node_signature } else { our_node_sig },
+                                               bitcoin_signature_1: if were_node_one { our_bitcoin_sig } else { msg.bitcoin_signature },
+                                               bitcoin_signature_2: if were_node_one { msg.bitcoin_signature } else { our_bitcoin_sig },
+                                               contents: announcement,
+                                       }, self.get_channel_update(chan).unwrap()) // can only fail if we're not in a ready state
+                               },
+                               None => return Err(HandleError{err: "Failed to find corresponding channel", msg: None})
+                       }
+               };
+               let mut pending_events = self.pending_events.lock().unwrap();
+               pending_events.push(events::Event::BroadcastChannelAnnouncement { msg: chan_announcement, update_msg: chan_update });
+               Ok(())
+       }
+}
+
+#[cfg(test)]
+mod tests {
+       use ln::channelmanager::{ChannelManager,OnionKeys};
+       use ln::router::{Route, RouteHop, Router};
+       use ln::msgs;
+       use ln::msgs::{MsgEncodable,ChannelMessageHandler,RoutingMessageHandler};
+       use util::test_utils;
+       use util::events::{Event, EventsProvider};
+
+       use bitcoin::util::misc::hex_bytes;
+       use bitcoin::util::hash::Sha256dHash;
+       use bitcoin::blockdata::block::BlockHeader;
+       use bitcoin::blockdata::transaction::Transaction;
+       use bitcoin::network::constants::Network;
+       use bitcoin::network::serialize::serialize;
+       use bitcoin::network::serialize::BitcoinHash;
+
+       use secp256k1::Secp256k1;
+       use secp256k1::key::{PublicKey,SecretKey};
+
+       use crypto::sha2::Sha256;
+       use crypto::digest::Digest;
+
+       use rand::{thread_rng,Rng};
+
+       use std::sync::Arc;
+       use std::default::Default;
+       use std::time::Instant;
+
+       fn build_test_onion_keys() -> Vec<OnionKeys> {
+               // Keys from BOLT 4, used in both test vector tests
+               let secp_ctx = Secp256k1::new();
+
+               let route = Route {
+                       hops: vec!(
+                                       RouteHop {
+                                               pubkey: PublicKey::from_slice(&secp_ctx, &hex_bytes("02eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619").unwrap()[..]).unwrap(),
+                                               short_channel_id: 0, fee_msat: 0, cltv_expiry_delta: 0 // Test vectors are garbage and not generateble from a RouteHop, we fill in payloads manually
+                                       },
+                                       RouteHop {
+                                               pubkey: PublicKey::from_slice(&secp_ctx, &hex_bytes("0324653eac434488002cc06bbfb7f10fe18991e35f9fe4302dbea6d2353dc0ab1c").unwrap()[..]).unwrap(),
+                                               short_channel_id: 0, fee_msat: 0, cltv_expiry_delta: 0 // Test vectors are garbage and not generateble from a RouteHop, we fill in payloads manually
+                                       },
+                                       RouteHop {
+                                               pubkey: PublicKey::from_slice(&secp_ctx, &hex_bytes("027f31ebc5462c1fdce1b737ecff52d37d75dea43ce11c74d25aa297165faa2007").unwrap()[..]).unwrap(),
+                                               short_channel_id: 0, fee_msat: 0, cltv_expiry_delta: 0 // Test vectors are garbage and not generateble from a RouteHop, we fill in payloads manually
+                                       },
+                                       RouteHop {
+                                               pubkey: PublicKey::from_slice(&secp_ctx, &hex_bytes("032c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e668680991").unwrap()[..]).unwrap(),
+                                               short_channel_id: 0, fee_msat: 0, cltv_expiry_delta: 0 // Test vectors are garbage and not generateble from a RouteHop, we fill in payloads manually
+                                       },
+                                       RouteHop {
+                                               pubkey: PublicKey::from_slice(&secp_ctx, &hex_bytes("02edabbd16b41c8371b92ef2f04c1185b4f03b6dcd52ba9b78d9d7c89c8f221145").unwrap()[..]).unwrap(),
+                                               short_channel_id: 0, fee_msat: 0, cltv_expiry_delta: 0 // Test vectors are garbage and not generateble from a RouteHop, we fill in payloads manually
+                                       },
+                       ),
+               };
+
+               let session_priv = SecretKey::from_slice(&secp_ctx, &hex_bytes("4141414141414141414141414141414141414141414141414141414141414141").unwrap()[..]).unwrap();
+
+               let onion_keys = ChannelManager::construct_onion_keys(&secp_ctx, &route, &session_priv).unwrap();
+               assert_eq!(onion_keys.len(), route.hops.len());
+               onion_keys
+       }
+
+       #[test]
+       fn onion_vectors() {
+               // Packet creation test vectors from BOLT 4
+               let onion_keys = build_test_onion_keys();
+
+               assert_eq!(onion_keys[0].shared_secret[..], hex_bytes("53eb63ea8a3fec3b3cd433b85cd62a4b145e1dda09391b348c4e1cd36a03ea66").unwrap()[..]);
+               assert_eq!(onion_keys[0].blinding_factor[..], hex_bytes("2ec2e5da605776054187180343287683aa6a51b4b1c04d6dd49c45d8cffb3c36").unwrap()[..]);
+               assert_eq!(onion_keys[0].ephemeral_pubkey.serialize()[..], hex_bytes("02eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619").unwrap()[..]);
+               assert_eq!(onion_keys[0].rho, hex_bytes("ce496ec94def95aadd4bec15cdb41a740c9f2b62347c4917325fcc6fb0453986").unwrap()[..]);
+               assert_eq!(onion_keys[0].mu, hex_bytes("b57061dc6d0a2b9f261ac410c8b26d64ac5506cbba30267a649c28c179400eba").unwrap()[..]);
+
+               assert_eq!(onion_keys[1].shared_secret[..], hex_bytes("a6519e98832a0b179f62123b3567c106db99ee37bef036e783263602f3488fae").unwrap()[..]);
+               assert_eq!(onion_keys[1].blinding_factor[..], hex_bytes("bf66c28bc22e598cfd574a1931a2bafbca09163df2261e6d0056b2610dab938f").unwrap()[..]);
+               assert_eq!(onion_keys[1].ephemeral_pubkey.serialize()[..], hex_bytes("028f9438bfbf7feac2e108d677e3a82da596be706cc1cf342b75c7b7e22bf4e6e2").unwrap()[..]);
+               assert_eq!(onion_keys[1].rho, hex_bytes("450ffcabc6449094918ebe13d4f03e433d20a3d28a768203337bc40b6e4b2c59").unwrap()[..]);
+               assert_eq!(onion_keys[1].mu, hex_bytes("05ed2b4a3fb023c2ff5dd6ed4b9b6ea7383f5cfe9d59c11d121ec2c81ca2eea9").unwrap()[..]);
+
+               assert_eq!(onion_keys[2].shared_secret[..], hex_bytes("3a6b412548762f0dbccce5c7ae7bb8147d1caf9b5471c34120b30bc9c04891cc").unwrap()[..]);
+               assert_eq!(onion_keys[2].blinding_factor[..], hex_bytes("a1f2dadd184eb1627049673f18c6325814384facdee5bfd935d9cb031a1698a5").unwrap()[..]);
+               assert_eq!(onion_keys[2].ephemeral_pubkey.serialize()[..], hex_bytes("03bfd8225241ea71cd0843db7709f4c222f62ff2d4516fd38b39914ab6b83e0da0").unwrap()[..]);
+               assert_eq!(onion_keys[2].rho, hex_bytes("11bf5c4f960239cb37833936aa3d02cea82c0f39fd35f566109c41f9eac8deea").unwrap()[..]);
+               assert_eq!(onion_keys[2].mu, hex_bytes("caafe2820fa00eb2eeb78695ae452eba38f5a53ed6d53518c5c6edf76f3f5b78").unwrap()[..]);
+
+               assert_eq!(onion_keys[3].shared_secret[..], hex_bytes("21e13c2d7cfe7e18836df50872466117a295783ab8aab0e7ecc8c725503ad02d").unwrap()[..]);
+               assert_eq!(onion_keys[3].blinding_factor[..], hex_bytes("7cfe0b699f35525029ae0fa437c69d0f20f7ed4e3916133f9cacbb13c82ff262").unwrap()[..]);
+               assert_eq!(onion_keys[3].ephemeral_pubkey.serialize()[..], hex_bytes("031dde6926381289671300239ea8e57ffaf9bebd05b9a5b95beaf07af05cd43595").unwrap()[..]);
+               assert_eq!(onion_keys[3].rho, hex_bytes("cbe784ab745c13ff5cffc2fbe3e84424aa0fd669b8ead4ee562901a4a4e89e9e").unwrap()[..]);
+               assert_eq!(onion_keys[3].mu, hex_bytes("5052aa1b3d9f0655a0932e50d42f0c9ba0705142c25d225515c45f47c0036ee9").unwrap()[..]);
+
+               assert_eq!(onion_keys[4].shared_secret[..], hex_bytes("b5756b9b542727dbafc6765a49488b023a725d631af688fc031217e90770c328").unwrap()[..]);
+               assert_eq!(onion_keys[4].blinding_factor[..], hex_bytes("c96e00dddaf57e7edcd4fb5954be5b65b09f17cb6d20651b4e90315be5779205").unwrap()[..]);
+               assert_eq!(onion_keys[4].ephemeral_pubkey.serialize()[..], hex_bytes("03a214ebd875aab6ddfd77f22c5e7311d7f77f17a169e599f157bbcdae8bf071f4").unwrap()[..]);
+               assert_eq!(onion_keys[4].rho, hex_bytes("034e18b8cc718e8af6339106e706c52d8df89e2b1f7e9142d996acf88df8799b").unwrap()[..]);
+               assert_eq!(onion_keys[4].mu, hex_bytes("8e45e5c61c2b24cb6382444db6698727afb063adecd72aada233d4bf273d975a").unwrap()[..]);
+
+               // Test vectors below are flat-out wrong: they claim to set outgoing_cltv_value to non-0 :/
+               let payloads = vec!(
+                       msgs::OnionHopData {
+                               realm: 0,
+                               data: msgs::OnionRealm0HopData {
+                                       short_channel_id: 0,
+                                       amt_to_forward: 0,
+                                       outgoing_cltv_value: 0,
+                               },
+                               hmac: [0; 32],
+                       },
+                       msgs::OnionHopData {
+                               realm: 0,
+                               data: msgs::OnionRealm0HopData {
+                                       short_channel_id: 0x0101010101010101,
+                                       amt_to_forward: 0x0100000001,
+                                       outgoing_cltv_value: 0,
+                               },
+                               hmac: [0; 32],
+                       },
+                       msgs::OnionHopData {
+                               realm: 0,
+                               data: msgs::OnionRealm0HopData {
+                                       short_channel_id: 0x0202020202020202,
+                                       amt_to_forward: 0x0200000002,
+                                       outgoing_cltv_value: 0,
+                               },
+                               hmac: [0; 32],
+                       },
+                       msgs::OnionHopData {
+                               realm: 0,
+                               data: msgs::OnionRealm0HopData {
+                                       short_channel_id: 0x0303030303030303,
+                                       amt_to_forward: 0x0300000003,
+                                       outgoing_cltv_value: 0,
+                               },
+                               hmac: [0; 32],
+                       },
+                       msgs::OnionHopData {
+                               realm: 0,
+                               data: msgs::OnionRealm0HopData {
+                                       short_channel_id: 0x0404040404040404,
+                                       amt_to_forward: 0x0400000004,
+                                       outgoing_cltv_value: 0,
+                               },
+                               hmac: [0; 32],
+                       },
+               );
+
+               let packet = ChannelManager::construct_onion_packet(payloads, onion_keys, hex_bytes("4242424242424242424242424242424242424242424242424242424242424242").unwrap()).unwrap();
+               // Just check the final packet encoding, as it includes all the per-hop vectors in it
+               // anyway...
+               assert_eq!(packet.encode(), hex_bytes("0002eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619e5f14350c2a76fc232b5e46d421e9615471ab9e0bc887beff8c95fdb878f7b3a716a996c7845c93d90e4ecbb9bde4ece2f69425c99e4bc820e44485455f135edc0d10f7d61ab590531cf08000179a333a347f8b4072f216400406bdf3bf038659793d4a1fd7b246979e3150a0a4cb052c9ec69acf0f48c3d39cd55675fe717cb7d80ce721caad69320c3a469a202f1e468c67eaf7a7cd8226d0fd32f7b48084dca885d56047694762b67021713ca673929c163ec36e04e40ca8e1c6d17569419d3039d9a1ec866abe044a9ad635778b961fc0776dc832b3a451bd5d35072d2269cf9b040f6b7a7dad84fb114ed413b1426cb96ceaf83825665ed5a1d002c1687f92465b49ed4c7f0218ff8c6c7dd7221d589c65b3b9aaa71a41484b122846c7c7b57e02e679ea8469b70e14fe4f70fee4d87b910cf144be6fe48eef24da475c0b0bcc6565ae82cd3f4e3b24c76eaa5616c6111343306ab35c1fe5ca4a77c0e314ed7dba39d6f1e0de791719c241a939cc493bea2bae1c1e932679ea94d29084278513c77b899cc98059d06a27d171b0dbdf6bee13ddc4fc17a0c4d2827d488436b57baa167544138ca2e64a11b43ac8a06cd0c2fba2d4d900ed2d9205305e2d7383cc98dacb078133de5f6fb6bed2ef26ba92cea28aafc3b9948dd9ae5559e8bd6920b8cea462aa445ca6a95e0e7ba52961b181c79e73bd581821df2b10173727a810c92b83b5ba4a0403eb710d2ca10689a35bec6c3a708e9e92f7d78ff3c5d9989574b00c6736f84c199256e76e19e78f0c98a9d580b4a658c84fc8f2096c2fbea8f5f8c59d0fdacb3be2802ef802abbecb3aba4acaac69a0e965abd8981e9896b1f6ef9d60f7a164b371af869fd0e48073742825e9434fc54da837e120266d53302954843538ea7c6c3dbfb4ff3b2fdbe244437f2a153ccf7bdb4c92aa08102d4f3cff2ae5ef86fab4653595e6a5837fa2f3e29f27a9cde5966843fb847a4a61f1e76c281fe8bb2b0a181d096100db5a1a5ce7a910238251a43ca556712eaadea167fb4d7d75825e440f3ecd782036d7574df8bceacb397abefc5f5254d2722215c53ff54af8299aaaad642c6d72a14d27882d9bbd539e1cc7a527526ba89b8c037ad09120e98ab042d3e8652b31ae0e478516bfaf88efca9f3676ffe99d2819dcaeb7610a626695f53117665d267d3f7abebd6bbd6733f645c72c389f03855bdf1e4b8075b516569b118233a0f0971d24b83113c0b096f5216a207ca99a7cddc81c130923fe3d91e7508c9ac5f2e914ff5dccab9e558566fa14efb34ac98d878580814b94b73acbfde9072f30b881f7f0fff42d4045d1ace6322d86a97d164aa84d93a60498065cc7c20e636f5862dc81531a88c60305a2e59a985be327a6902e4bed986dbf4a0b50c217af0ea7fdf9ab37f9ea1a1aaa72f54cf40154ea9b269f1a7c09f9f43245109431a175d50e2db0132337baa0ef97eed0fcf20489da36b79a1172faccc2f7ded7c60e00694282d93359c4682135642bc81f433574aa8ef0c97b4ade7ca372c5ffc23c7eddd839bab4e0f14d6df15c9dbeab176bec8b5701cf054eb3072f6dadc98f88819042bf10c407516ee58bce33fbe3b3d86a54255e577db4598e30a135361528c101683a5fcde7e8ba53f3456254be8f45fe3a56120ae96ea3773631fcb3873aa3abd91bcff00bd38bd43697a2e789e00da6077482e7b1b1a677b5afae4c54e6cbdf7377b694eb7d7a5b913476a5be923322d3de06060fd5e819635232a2cf4f0731da13b8546d1d6d4f8d75b9fce6c2341a71b0ea6f780df54bfdb0dd5cd9855179f602f9172307c7268724c3618e6817abd793adc214a0dc0bc616816632f27ea336fb56dfd").unwrap());
+       }
+
+       #[test]
+       fn test_failure_packet_onion() {
+               // Returning Errors test vectors from BOLT 4
+
+               let onion_keys = build_test_onion_keys();
+               let onion_error = ChannelManager::build_failure_packet(&onion_keys[4].shared_secret, 0x2002, &[0; 0]);
+               assert_eq!(onion_error.encode(), hex_bytes("4c2fc8bc08510334b6833ad9c3e79cd1b52ae59dfe5c2a4b23ead50f09f7ee0b0002200200fe0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").unwrap());
+
+               let onion_packet_1 = ChannelManager::encrypt_failure_packet(&onion_keys[4].shared_secret, &onion_error.encode()[..]);
+               assert_eq!(onion_packet_1.data, hex_bytes("a5e6bd0c74cb347f10cce367f949098f2457d14c046fd8a22cb96efb30b0fdcda8cb9168b50f2fd45edd73c1b0c8b33002df376801ff58aaa94000bf8a86f92620f343baef38a580102395ae3abf9128d1047a0736ff9b83d456740ebbb4aeb3aa9737f18fb4afb4aa074fb26c4d702f42968888550a3bded8c05247e045b866baef0499f079fdaeef6538f31d44deafffdfd3afa2fb4ca9082b8f1c465371a9894dd8c243fb4847e004f5256b3e90e2edde4c9fb3082ddfe4d1e734cacd96ef0706bf63c9984e22dc98851bcccd1c3494351feb458c9c6af41c0044bea3c47552b1d992ae542b17a2d0bba1a096c78d169034ecb55b6e3a7263c26017f033031228833c1daefc0dedb8cf7c3e37c9c37ebfe42f3225c326e8bcfd338804c145b16e34e4").unwrap());
+
+               let onion_packet_2 = ChannelManager::encrypt_failure_packet(&onion_keys[3].shared_secret, &onion_packet_1.data[..]);
+               assert_eq!(onion_packet_2.data, hex_bytes("c49a1ce81680f78f5f2000cda36268de34a3f0a0662f55b4e837c83a8773c22aa081bab1616a0011585323930fa5b9fae0c85770a2279ff59ec427ad1bbff9001c0cd1497004bd2a0f68b50704cf6d6a4bf3c8b6a0833399a24b3456961ba00736785112594f65b6b2d44d9f5ea4e49b5e1ec2af978cbe31c67114440ac51a62081df0ed46d4a3df295da0b0fe25c0115019f03f15ec86fabb4c852f83449e812f141a9395b3f70b766ebbd4ec2fae2b6955bd8f32684c15abfe8fd3a6261e52650e8807a92158d9f1463261a925e4bfba44bd20b166d532f0017185c3a6ac7957adefe45559e3072c8dc35abeba835a8cb01a71a15c736911126f27d46a36168ca5ef7dccd4e2886212602b181463e0dd30185c96348f9743a02aca8ec27c0b90dca270").unwrap());
+
+               let onion_packet_3 = ChannelManager::encrypt_failure_packet(&onion_keys[2].shared_secret, &onion_packet_2.data[..]);
+               assert_eq!(onion_packet_3.data, hex_bytes("a5d3e8634cfe78b2307d87c6d90be6fe7855b4f2cc9b1dfb19e92e4b79103f61ff9ac25f412ddfb7466e74f81b3e545563cdd8f5524dae873de61d7bdfccd496af2584930d2b566b4f8d3881f8c043df92224f38cf094cfc09d92655989531524593ec6d6caec1863bdfaa79229b5020acc034cd6deeea1021c50586947b9b8e6faa83b81fbfa6133c0af5d6b07c017f7158fa94f0d206baf12dda6b68f785b773b360fd0497e16cc402d779c8d48d0fa6315536ef0660f3f4e1865f5b38ea49c7da4fd959de4e83ff3ab686f059a45c65ba2af4a6a79166aa0f496bf04d06987b6d2ea205bdb0d347718b9aeff5b61dfff344993a275b79717cd815b6ad4c0beb568c4ac9c36ff1c315ec1119a1993c4b61e6eaa0375e0aaf738ac691abd3263bf937e3").unwrap());
+
+               let onion_packet_4 = ChannelManager::encrypt_failure_packet(&onion_keys[1].shared_secret, &onion_packet_3.data[..]);
+               assert_eq!(onion_packet_4.data, hex_bytes("aac3200c4968f56b21f53e5e374e3a2383ad2b1b6501bbcc45abc31e59b26881b7dfadbb56ec8dae8857add94e6702fb4c3a4de22e2e669e1ed926b04447fc73034bb730f4932acd62727b75348a648a1128744657ca6a4e713b9b646c3ca66cac02cdab44dd3439890ef3aaf61708714f7375349b8da541b2548d452d84de7084bb95b3ac2345201d624d31f4d52078aa0fa05a88b4e20202bd2b86ac5b52919ea305a8949de95e935eed0319cf3cf19ebea61d76ba92532497fcdc9411d06bcd4275094d0a4a3c5d3a945e43305a5a9256e333e1f64dbca5fcd4e03a39b9012d197506e06f29339dfee3331995b21615337ae060233d39befea925cc262873e0530408e6990f1cbd233a150ef7b004ff6166c70c68d9f8c853c1abca640b8660db2921").unwrap());
+
+               let onion_packet_5 = ChannelManager::encrypt_failure_packet(&onion_keys[0].shared_secret, &onion_packet_4.data[..]);
+               assert_eq!(onion_packet_5.data, hex_bytes("9c5add3963fc7f6ed7f148623c84134b5647e1306419dbe2174e523fa9e2fbed3a06a19f899145610741c83ad40b7712aefaddec8c6baf7325d92ea4ca4d1df8bce517f7e54554608bf2bd8071a4f52a7a2f7ffbb1413edad81eeea5785aa9d990f2865dc23b4bc3c301a94eec4eabebca66be5cf638f693ec256aec514620cc28ee4a94bd9565bc4d4962b9d3641d4278fb319ed2b84de5b665f307a2db0f7fbb757366067d88c50f7e829138fde4f78d39b5b5802f1b92a8a820865af5cc79f9f30bc3f461c66af95d13e5e1f0381c184572a91dee1c849048a647a1158cf884064deddbf1b0b88dfe2f791428d0ba0f6fb2f04e14081f69165ae66d9297c118f0907705c9c4954a199bae0bb96fad763d690e7daa6cfda59ba7f2c8d11448b604d12d").unwrap());
+       }
+
+       static mut CHAN_COUNT: u16 = 0;
+       fn confirm_transaction(chain: &test_utils::TestWatchInterface, tx: &Transaction) {
+               let mut header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
+               let chan_id = unsafe { CHAN_COUNT };
+               chain.watch_util.do_call_block_connected(&header, 1, &[tx; 1], &[chan_id as u32; 1]);
+               for i in 2..100 {
+                       header = BlockHeader { version: 0x20000000, prev_blockhash: header.bitcoin_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
+                       chain.watch_util.do_call_block_connected(&header, i, &[tx; 0], &[0; 0]);
+               }
+       }
+
+       fn create_chan_between_nodes(node_a: &ChannelManager, chain_a: &test_utils::TestWatchInterface, node_b: &ChannelManager, chain_b: &test_utils::TestWatchInterface) -> (msgs::ChannelAnnouncement, msgs::ChannelUpdate, msgs::ChannelUpdate) {
+               let open_chan = node_a.create_channel(node_b.get_our_node_id(), (1 << 24) - 1, 42).unwrap();
+               let accept_chan = node_b.handle_open_channel(&node_a.get_our_node_id(), &open_chan).unwrap();
+               node_a.handle_accept_channel(&node_b.get_our_node_id(), &accept_chan).unwrap();
+
+               let chan_id = unsafe { CHAN_COUNT };
+               let tx = Transaction { version: chan_id as u32, lock_time: 0, input: Vec::new(), output: Vec::new(), witness: Vec::new() };
+               let funding_output = (Sha256dHash::from_data(&serialize(&tx).unwrap()[..]), chan_id);
+
+               let events_1 = node_a.get_and_clear_pending_events();
+               assert_eq!(events_1.len(), 1);
+               match events_1[0] {
+                       Event::FundingGenerationReady { ref temporary_channel_id, ref channel_value_satoshis, output_script: _, user_channel_id } => {
+                               assert_eq!(*channel_value_satoshis, (1 << 24) - 1);
+                               assert_eq!(user_channel_id, 42);
+
+                               node_a.funding_transaction_generated(&temporary_channel_id, funding_output.clone());
+                               //TODO: Check that we got added to chan_monitor_a!
+                       },
+                       _ => panic!("Unexpected event"),
+               }
+
+               let events_2 = node_a.get_and_clear_pending_events();
+               assert_eq!(events_2.len(), 1);
+               let funding_signed = match events_2[0] {
+                       Event::SendFundingCreated { ref node_id, ref msg } => {
+                               assert_eq!(*node_id, node_b.get_our_node_id());
+                               node_b.handle_funding_created(&node_a.get_our_node_id(), msg).unwrap()
+                               //TODO: Check that we got added to chan_monitor_b!
+                       },
+                       _ => panic!("Unexpected event"),
+               };
+
+               node_a.handle_funding_signed(&node_b.get_our_node_id(), &funding_signed).unwrap();
+
+               let events_3 = node_a.get_and_clear_pending_events();
+               assert_eq!(events_3.len(), 1);
+               match events_3[0] {
+                       Event::FundingBroadcastSafe { ref funding_txo, user_channel_id } => {
+                               assert_eq!(user_channel_id, 42);
+                               assert_eq!(*funding_txo, funding_output);
+                       },
+                       _ => panic!("Unexpected event"),
+               };
+
+               confirm_transaction(&chain_a, &tx);
+               let events_4 = node_a.get_and_clear_pending_events();
+               assert_eq!(events_4.len(), 1);
+               match events_4[0] {
+                       Event::SendFundingLocked { ref node_id, ref msg, ref announcement_sigs } => {
+                               assert_eq!(*node_id, node_b.get_our_node_id());
+                               assert!(announcement_sigs.is_none());
+                               node_b.handle_funding_locked(&node_a.get_our_node_id(), msg).unwrap()
+                       },
+                       _ => panic!("Unexpected event"),
+               };
+
+               confirm_transaction(&chain_b, &tx);
+               let events_5 = node_b.get_and_clear_pending_events();
+               assert_eq!(events_5.len(), 1);
+               let as_announcement_sigs = match events_5[0] {
+                       Event::SendFundingLocked { ref node_id, ref msg, ref announcement_sigs } => {
+                               assert_eq!(*node_id, node_a.get_our_node_id());
+                               let as_announcement_sigs = node_a.handle_funding_locked(&node_b.get_our_node_id(), msg).unwrap().unwrap();
+                               node_a.handle_announcement_signatures(&node_b.get_our_node_id(), &(*announcement_sigs).clone().unwrap()).unwrap();
+                               as_announcement_sigs
+                       },
+                       _ => panic!("Unexpected event"),
+               };
+
+               let events_6 = node_a.get_and_clear_pending_events();
+               assert_eq!(events_6.len(), 1);
+               let (announcement, as_update) = match events_6[0] {
+                       Event::BroadcastChannelAnnouncement { ref msg, ref update_msg } => {
+                               (msg, update_msg)
+                       },
+                       _ => panic!("Unexpected event"),
+               };
+
+               node_b.handle_announcement_signatures(&node_a.get_our_node_id(), &as_announcement_sigs).unwrap();
+               let events_7 = node_b.get_and_clear_pending_events();
+               assert_eq!(events_7.len(), 1);
+               let bs_update = match events_7[0] {
+                       Event::BroadcastChannelAnnouncement { ref msg, ref update_msg } => {
+                               assert!(*announcement == *msg);
+                               update_msg
+                       },
+                       _ => panic!("Unexpected event"),
+               };
+
+               unsafe {
+                       CHAN_COUNT += 1;
+               }
+
+               ((*announcement).clone(), (*as_update).clone(), (*bs_update).clone())
+       }
+
+       struct SendEvent {
+               node_id: PublicKey,
+               msgs: Vec<msgs::UpdateAddHTLC>,
+               commitment_msg: msgs::CommitmentSigned,
+       }
+       impl SendEvent {
+               fn from_event(event: Event) -> SendEvent {
+                       match event {
+                               Event::SendHTLCs{ node_id, msgs, commitment_msg } => {
+                                       SendEvent { node_id: node_id, msgs: msgs, commitment_msg: commitment_msg }
+                               },
+                               _ => panic!("Unexpected event type!"),
+                       }
+               }
+       }
+
+       static mut PAYMENT_COUNT: u8 = 0;
+       fn send_payment(origin_node: &ChannelManager, origin_router: &Router, expected_route: &[&ChannelManager]) {
+               let route = origin_router.get_route(&expected_route.last().unwrap().get_our_node_id(), &Vec::new(), 1000000, 142).unwrap();
+               assert_eq!(route.hops.len(), expected_route.len());
+               for (node, hop) in expected_route.iter().zip(route.hops.iter()) {
+                       assert_eq!(hop.pubkey, node.get_our_node_id());
+               }
+
+               let payment_preimage = unsafe { [PAYMENT_COUNT; 32] };
+               unsafe { PAYMENT_COUNT += 1 };
+               let our_payment_hash = {
+                       let mut sha = Sha256::new();
+                       sha.input(&payment_preimage[..]);
+                       let mut ret = [0; 32];
+                       sha.result(&mut ret);
+                       ret
+               };
+
+               let mut payment_event = {
+                       let msgs = origin_node.send_payment(&route, our_payment_hash).unwrap().unwrap();
+                       SendEvent {
+                               node_id: expected_route[0].get_our_node_id(),
+                               msgs: vec!(msgs.0),
+                               commitment_msg: msgs.1,
+                       }
+               };
+               let mut prev_node = origin_node;
+
+               for (idx, node) in expected_route.iter().enumerate() {
+                       assert_eq!(node.get_our_node_id(), payment_event.node_id);
+
+                       node.handle_update_add_htlc(&prev_node.get_our_node_id(), &payment_event.msgs[0]).unwrap();
+                       let revoke_and_ack = node.handle_commitment_signed(&prev_node.get_our_node_id(), &payment_event.commitment_msg).unwrap();
+                       prev_node.handle_revoke_and_ack(&node.get_our_node_id(), &revoke_and_ack).unwrap();
+
+                       let events_1 = node.get_and_clear_pending_events();
+                       assert_eq!(events_1.len(), 1);
+                       match events_1[0] {
+                               Event::PendingHTLCsForwardable { .. } => { },
+                               _ => panic!("Unexpected event"),
+                       };
+
+                       node.pending_htlcs_forwardable.lock().unwrap().next_forward = Instant::now();
+                       node.process_pending_htlc_forward();
+
+                       let mut events_2 = node.get_and_clear_pending_events();
+                       assert_eq!(events_2.len(), 1);
+                       if idx == expected_route.len() - 1 {
+                               match events_2[0] {
+                                       Event::PaymentReceived { ref payment_hash, amt } => {
+                                               assert_eq!(our_payment_hash, *payment_hash);
+                                               assert_eq!(amt, 1000000);
+                                       },
+                                       _ => panic!("Unexpected event"),
+                               }
+                       } else {
+                               for event in events_2.drain(..) {
+                                       payment_event = SendEvent::from_event(event);
+                               }
+                               assert_eq!(payment_event.msgs.len(), 1);
+                       }
+
+                       prev_node = node;
+               }
+
+               assert!(expected_route.last().unwrap().claim_funds(payment_preimage));
+
+               let mut expected_next_node = expected_route.last().unwrap().get_our_node_id();
+               let mut prev_node = expected_route.last().unwrap();
+               let mut next_msg = None;
+               for node in expected_route.iter().rev() {
+                       assert_eq!(expected_next_node, node.get_our_node_id());
+                       match next_msg {
+                               Some(msg) => {
+                                       assert!(node.handle_update_fulfill_htlc(&prev_node.get_our_node_id(), &msg).unwrap().is_none());
+                               }, None => {}
+                       }
+
+                       let events = node.get_and_clear_pending_events();
+                       assert_eq!(events.len(), 1);
+                       match events[0] {
+                               Event::SendFulfillHTLC { ref node_id, ref msg } => {
+                                       expected_next_node = node_id.clone();
+                                       next_msg = Some(msg.clone());
+                               },
+                               _ => panic!("Unexpected event"),
+                       };
+
+                       prev_node = node;
+               }
+
+               assert_eq!(expected_next_node, origin_node.get_our_node_id());
+               assert!(origin_node.handle_update_fulfill_htlc(&expected_route.first().unwrap().get_our_node_id(), &next_msg.unwrap()).unwrap().is_none());
+       }
+
+       #[test]
+       fn fake_network_test() {
+               // Simple test which builds a network of ChannelManagers, connects them to each other, and
+               // tests that payments get routed and transactions broadcast in semi-reasonable ways.
+               let mut rng = thread_rng();
+               let secp_ctx = Secp256k1::new();
+
+               let feeest_1 = Arc::new(test_utils::TestFeeEstimator { sat_per_vbyte: 1 });
+               let chain_monitor_1 = Arc::new(test_utils::TestWatchInterface::new());
+               let chan_monitor_1 = Arc::new(test_utils::TestChannelMonitor{});
+               let node_id_1 = {
+                       let mut key_slice = [0; 32];
+                       rng.fill_bytes(&mut key_slice);
+                       SecretKey::from_slice(&secp_ctx, &key_slice).unwrap()
+               };
+               let node_1 = ChannelManager::new(node_id_1.clone(), 0, true, Network::Testnet, feeest_1.clone(), chan_monitor_1.clone(), chain_monitor_1.clone()).unwrap();
+               let router_1 = Router::new(PublicKey::from_secret_key(&secp_ctx, &node_id_1).unwrap());
+
+               let feeest_2 = Arc::new(test_utils::TestFeeEstimator { sat_per_vbyte: 1 });
+               let chain_monitor_2 = Arc::new(test_utils::TestWatchInterface::new());
+               let chan_monitor_2 = Arc::new(test_utils::TestChannelMonitor{});
+               let node_id_2 = {
+                       let mut key_slice = [0; 32];
+                       rng.fill_bytes(&mut key_slice);
+                       SecretKey::from_slice(&secp_ctx, &key_slice).unwrap()
+               };
+               let node_2 = ChannelManager::new(node_id_2.clone(), 0, true, Network::Testnet, feeest_2.clone(), chan_monitor_2.clone(), chain_monitor_2.clone()).unwrap();
+               let router_2 = Router::new(PublicKey::from_secret_key(&secp_ctx, &node_id_2).unwrap());
+
+               let feeest_3 = Arc::new(test_utils::TestFeeEstimator { sat_per_vbyte: 1 });
+               let chain_monitor_3 = Arc::new(test_utils::TestWatchInterface::new());
+               let chan_monitor_3 = Arc::new(test_utils::TestChannelMonitor{});
+               let node_id_3 = {
+                       let mut key_slice = [0; 32];
+                       rng.fill_bytes(&mut key_slice);
+                       SecretKey::from_slice(&secp_ctx, &key_slice).unwrap()
+               };
+               let node_3 = ChannelManager::new(node_id_3.clone(), 0, true, Network::Testnet, feeest_3.clone(), chan_monitor_3.clone(), chain_monitor_3.clone()).unwrap();
+               let router_3 = Router::new(PublicKey::from_secret_key(&secp_ctx, &node_id_3).unwrap());
+
+               let feeest_4 = Arc::new(test_utils::TestFeeEstimator { sat_per_vbyte: 1 });
+               let chain_monitor_4 = Arc::new(test_utils::TestWatchInterface::new());
+               let chan_monitor_4 = Arc::new(test_utils::TestChannelMonitor{});
+               let node_id_4 = {
+                       let mut key_slice = [0; 32];
+                       rng.fill_bytes(&mut key_slice);
+                       SecretKey::from_slice(&secp_ctx, &key_slice).unwrap()
+               };
+               let node_4 = ChannelManager::new(node_id_4.clone(), 0, true, Network::Testnet, feeest_4.clone(), chan_monitor_4.clone(), chain_monitor_4.clone()).unwrap();
+               let router_4 = Router::new(PublicKey::from_secret_key(&secp_ctx, &node_id_4).unwrap());
+
+               // Create some initial channels
+               let chan_announcement_1 = create_chan_between_nodes(&node_1, &chain_monitor_1, &node_2, &chain_monitor_2);
+               for router in vec!(&router_1, &router_2, &router_3, &router_4) {
+                       assert!(router.handle_channel_announcement(&chan_announcement_1.0).unwrap());
+                       router.handle_channel_update(&chan_announcement_1.1).unwrap();
+                       router.handle_channel_update(&chan_announcement_1.2).unwrap();
+               }
+               let chan_announcement_2 = create_chan_between_nodes(&node_2, &chain_monitor_2, &node_3, &chain_monitor_3);
+               for router in vec!(&router_1, &router_2, &router_3, &router_4) {
+                       assert!(router.handle_channel_announcement(&chan_announcement_2.0).unwrap());
+                       router.handle_channel_update(&chan_announcement_2.1).unwrap();
+                       router.handle_channel_update(&chan_announcement_2.2).unwrap();
+               }
+               let chan_announcement_3 = create_chan_between_nodes(&node_3, &chain_monitor_3, &node_4, &chain_monitor_4);
+               for router in vec!(&router_1, &router_2, &router_3, &router_4) {
+                       assert!(router.handle_channel_announcement(&chan_announcement_3.0).unwrap());
+                       router.handle_channel_update(&chan_announcement_3.1).unwrap();
+                       router.handle_channel_update(&chan_announcement_3.2).unwrap();
+               }
+
+               // Send some payments
+               send_payment(&node_1, &router_1, &vec!(&*node_2, &*node_3, &*node_4)[..]);
+               send_payment(&node_2, &router_2, &vec!(&*node_3, &*node_4)[..]);
+               send_payment(&node_4, &router_4, &vec!(&*node_3, &*node_2, &*node_1)[..]);
+
+               // Add a new channel that skips 3
+               let chan_announcement_4 = create_chan_between_nodes(&node_2, &chain_monitor_2, &node_4, &chain_monitor_4);
+               for router in vec!(&router_1, &router_2, &router_3, &router_4) {
+                       assert!(router.handle_channel_announcement(&chan_announcement_4.0).unwrap());
+                       router.handle_channel_update(&chan_announcement_4.1).unwrap();
+                       router.handle_channel_update(&chan_announcement_4.2).unwrap();
+               }
+
+               send_payment(&node_1, &router_1, &vec!(&*node_2, &*node_4)[..]);
+
+               // Check that we processed all pending events
+               for node in vec!(&node_1, &node_2, &node_3, &node_4) {
+                       assert_eq!(node.get_and_clear_pending_events().len(), 0);
+               }
+       }
+}
diff --git a/src/ln/channelmonitor.rs b/src/ln/channelmonitor.rs
new file mode 100644 (file)
index 0000000..e463b93
--- /dev/null
@@ -0,0 +1,826 @@
+use bitcoin::blockdata::block::BlockHeader;
+use bitcoin::blockdata::transaction::{TxIn,TxOut,SigHashType,Transaction};
+use bitcoin::blockdata::script::Script;
+use bitcoin::util::hash::Sha256dHash;
+use bitcoin::util::bip143;
+
+use crypto::sha2::Sha256;
+use crypto::digest::Digest;
+
+use secp256k1::{Secp256k1,Message,Signature};
+use secp256k1::key::{SecretKey,PublicKey};
+
+use ln::msgs::HandleError;
+use ln::chan_utils;
+use ln::chan_utils::HTLCOutputInCommitment;
+use chain::chaininterface::{ChainListener,ChainWatchInterface};
+
+use std::collections::HashMap;
+use std::sync::{Arc,Mutex};
+use std::{hash,cmp};
+
+/// Simple trait indicating ability to track a set of ChannelMonitors and multiplex events between
+/// them. Generally should be implemented by keeping a local SimpleManyChannelMonitor and passing
+/// events to it, while also taking any add_update_monitor events and passing them to some remote
+/// server(s).
+pub trait ManyChannelMonitor: Send + Sync {
+       /// Adds or updates a monitor for the given funding_txid+funding_output_index.
+       fn add_update_monitor(&self, funding_txo: (Sha256dHash, u16), monitor: ChannelMonitor) -> Result<(), HandleError>;
+}
+
+/// A simple implementation of a ManyChannelMonitor and ChainListener. Can be used to create a
+/// watchtower or watch our own channels.
+/// Note that you must provide your own key by which to refer to channels.
+/// If you're accepting remote monitors (ie are implementing a watchtower), you must verify that
+/// users cannot overwrite a given channel by providing a duplicate key. ie you should probably
+/// index by a PublicKey which is required to sign any updates.
+/// If you're using this for local monitoring of your own channels, you probably want to use
+/// (Sha256dHash, u16) as the key, which will give you a ManyChannelMonitor implementation.
+pub struct SimpleManyChannelMonitor<Key> {
+       monitors: Mutex<HashMap<Key, ChannelMonitor>>,
+       chain_monitor: Arc<ChainWatchInterface>,
+}
+
+impl<Key : Send + cmp::Eq + hash::Hash> ChainListener for SimpleManyChannelMonitor<Key> {
+       fn block_connected(&self, _header: &BlockHeader, height: u32, txn_matched: &[&Transaction], _indexes_of_txn_matched: &[u32]) {
+               let monitors = self.monitors.lock().unwrap();
+               for monitor in monitors.values() {
+                       monitor.block_connected(txn_matched, height, &*self.chain_monitor);
+               }
+       }
+
+       fn block_disconnected(&self, _: &BlockHeader) { }
+}
+
+impl<Key : Send + cmp::Eq + hash::Hash + 'static> SimpleManyChannelMonitor<Key> {
+       pub fn new(chain_monitor: Arc<ChainWatchInterface>) -> Arc<SimpleManyChannelMonitor<Key>> {
+               let res = Arc::new(SimpleManyChannelMonitor {
+                       monitors: Mutex::new(HashMap::new()),
+                       chain_monitor: chain_monitor,
+               });
+               let weak_res = Arc::downgrade(&res);
+               res.chain_monitor.register_listener(weak_res);
+               res
+       }
+
+       pub fn add_update_monitor_by_key(&self, key: Key, monitor: ChannelMonitor) -> Result<(), HandleError> {
+               let mut monitors = self.monitors.lock().unwrap();
+               match monitors.get_mut(&key) {
+                       Some(orig_monitor) => return orig_monitor.insert_combine(monitor),
+                       None => {}
+               };
+               match monitor.funding_txo {
+                       None => self.chain_monitor.watch_all_txn(),
+                       Some((funding_txid, funding_output_index)) => self.chain_monitor.install_watch_outpoint((funding_txid, funding_output_index as u32)),
+               }
+               monitors.insert(key, monitor);
+               Ok(())
+       }
+}
+
+impl ManyChannelMonitor for SimpleManyChannelMonitor<(Sha256dHash, u16)> {
+       fn add_update_monitor(&self, funding_txo: (Sha256dHash, u16), monitor: ChannelMonitor) -> Result<(), HandleError> {
+               self.add_update_monitor_by_key(funding_txo, monitor)
+       }
+}
+
+/// If an HTLC expires within this many blocks, don't try to claim it directly, instead broadcast
+/// the HTLC-Success/HTLC-Timeout transaction and claim the revocation from that.
+const CLTV_CLAIM_BUFFER: u32 = 12;
+
+#[derive(Clone)]
+enum RevocationStorage {
+       PrivMode {
+               revocation_base_key: SecretKey,
+       },
+       SigsMode {
+               revocation_base_key: PublicKey,
+               sigs: HashMap<Sha256dHash, Signature>,
+       }
+}
+
+#[derive(Clone)]
+struct PerCommitmentTransactionData {
+       revoked_output_index: u32,
+       htlcs: Vec<(HTLCOutputInCommitment, Signature)>,
+}
+
+#[derive(Clone)]
+pub struct ChannelMonitor {
+       funding_txo: Option<(Sha256dHash, u16)>,
+       commitment_transaction_number_obscure_factor: u64,
+
+       revocation_base_key: RevocationStorage,
+       delayed_payment_base_key: PublicKey,
+       htlc_base_key: PublicKey,
+       their_htlc_base_key: Option<PublicKey>,
+       to_self_delay: u16,
+
+       old_secrets: [([u8; 32], u64); 49],
+       claimable_outpoints: HashMap<Sha256dHash, PerCommitmentTransactionData>,
+       payment_preimages: Vec<[u8; 32]>,
+
+       destination_script: Script,
+       secp_ctx: Secp256k1, //TODO: dedup this a bit...
+}
+
+impl ChannelMonitor {
+       pub fn new(revocation_base_key: &SecretKey, delayed_payment_base_key: &PublicKey, htlc_base_key: &PublicKey, to_self_delay: u16, destination_script: Script) -> ChannelMonitor {
+               ChannelMonitor {
+                       funding_txo: None,
+                       commitment_transaction_number_obscure_factor: 0,
+
+                       revocation_base_key: RevocationStorage::PrivMode {
+                               revocation_base_key: revocation_base_key.clone(),
+                       },
+                       delayed_payment_base_key: delayed_payment_base_key.clone(),
+                       htlc_base_key: htlc_base_key.clone(),
+                       their_htlc_base_key: None,
+                       to_self_delay: to_self_delay,
+
+                       old_secrets: [([0; 32], 1 << 48); 49],
+                       claimable_outpoints: HashMap::new(),
+                       payment_preimages: Vec::new(),
+
+                       destination_script: destination_script,
+                       secp_ctx: Secp256k1::new(),
+               }
+       }
+
+       #[inline]
+       fn place_secret(idx: u64) -> u8 {
+               for i in 0..48 {
+                       if idx & (1 << i) == (1 << i) {
+                               return i
+                       }
+               }
+               48
+       }
+
+       #[inline]
+       fn derive_secret(secret: [u8; 32], bits: u8, idx: u64) -> [u8; 32] {
+               let mut res: [u8; 32] = secret;
+               for i in 0..bits {
+                       let bitpos = bits - 1 - i;
+                       if idx & (1 << bitpos) == (1 << bitpos) {
+                               res[(bitpos / 8) as usize] ^= 1 << (bitpos & 7);
+                               let mut sha = Sha256::new();
+                               sha.input(&res);
+                               sha.result(&mut res);
+                       }
+               }
+               res
+       }
+
+       /// Inserts a revocation secret into this channel monitor. Requires the revocation_base_key of
+       /// the node which we are monitoring the channel on behalf of in order to generate signatures
+       /// over revocation-claim transactions.
+       pub fn provide_secret(&mut self, idx: u64, secret: [u8; 32]) -> Result<(), HandleError> {
+               let pos = ChannelMonitor::place_secret(idx);
+               for i in 0..pos {
+                       let (old_secret, old_idx) = self.old_secrets[i as usize];
+                       if ChannelMonitor::derive_secret(secret, pos, old_idx) != old_secret {
+                               return Err(HandleError{err: "Previous secret did not match new one", msg: None})
+                       }
+               }
+               self.old_secrets[pos as usize] = (secret, idx);
+               Ok(())
+       }
+
+       /// Informs this watcher of the set of HTLC outputs in a commitment transaction which our
+       /// counterparty may broadcast. This allows us to reconstruct the commitment transaction's
+       /// outputs fully, claiming revoked, unexpired HTLC outputs as well as revoked refund outputs.
+       /// TODO: Doc new params!
+       /// TODO: This seems to be wrong...we should be calling this from commitment_signed, but we
+       /// should be calling this about remote transactions, ie ones that they can revoke_and_ack...
+       pub fn provide_tx_info(&mut self, commitment_tx: &Transaction, revokeable_out_index: u32, htlc_outputs: Vec<(HTLCOutputInCommitment, Signature)>) {
+               // TODO: Encrypt the htlc_outputs data with the single-hash of the commitment transaction
+               // so that a remote monitor doesn't learn anything unless there is a malicious close.
+               self.claimable_outpoints.insert(commitment_tx.txid(), PerCommitmentTransactionData{
+                       revoked_output_index: revokeable_out_index,
+                       htlcs: htlc_outputs
+               });
+       }
+
+       pub fn insert_combine(&mut self, other: ChannelMonitor) -> Result<(), HandleError> {
+               match self.funding_txo {
+                       Some(txo) => if other.funding_txo.is_some() && other.funding_txo.unwrap() != txo {
+                               return Err(HandleError{err: "Funding transaction outputs are not identical!", msg: None});
+                       },
+                       None => if other.funding_txo.is_some() {
+                               self.funding_txo = other.funding_txo;
+                       }
+               }
+               let other_max_secret = other.get_min_seen_secret();
+               if self.get_min_seen_secret() > other_max_secret {
+                       self.provide_secret(other_max_secret, other.get_secret(other_max_secret).unwrap())
+               } else { Ok(()) }
+       }
+
+       /// Panics if commitment_transaction_number_obscure_factor doesn't fit in 48 bits
+       pub fn set_commitment_obscure_factor(&mut self, commitment_transaction_number_obscure_factor: u64) {
+               assert!(commitment_transaction_number_obscure_factor < (1 << 48));
+               self.commitment_transaction_number_obscure_factor = commitment_transaction_number_obscure_factor;
+       }
+
+       /// Allows this monitor to scan only for transactions which are applicable. Note that this is
+       /// optional, without it this monitor cannot be used in an SPV client, but you may wish to
+       /// avoid this (or call unset_funding_info) on a monitor you wish to send to a watchtower as it
+       /// provides slightly better privacy.
+       pub fn set_funding_info(&mut self, funding_txid: Sha256dHash, funding_output_index: u16) {
+               self.funding_txo = Some((funding_txid, funding_output_index));
+       }
+
+       pub fn set_their_htlc_base_key(&mut self, their_htlc_base_key: &PublicKey) {
+               self.their_htlc_base_key = Some(their_htlc_base_key.clone());
+       }
+
+       pub fn unset_funding_info(&mut self) {
+               self.funding_txo = None;
+       }
+
+       pub fn get_funding_txo(&self) -> Option<(Sha256dHash, u16)> {
+               self.funding_txo
+       }
+
+       //TODO: Functions to serialize/deserialize (with different forms depending on which information
+       //we want to leave out (eg funding_txo, etc).
+
+       /// Can only fail if idx is < get_min_seen_secret
+       pub fn get_secret(&self, idx: u64) -> Result<[u8; 32], HandleError> {
+               for i in 0..self.old_secrets.len() {
+                       if (idx & (!((1 << i) - 1))) == self.old_secrets[i].1 {
+                               return Ok(ChannelMonitor::derive_secret(self.old_secrets[i].0, i as u8, idx))
+                       }
+               }
+               assert!(idx < self.get_min_seen_secret());
+               Err(HandleError{err: "idx too low", msg: None})
+       }
+
+       pub fn get_min_seen_secret(&self) -> u64 {
+               //TODO This can be optimized?
+               let mut min = 1 << 48;
+               for &(_, idx) in self.old_secrets.iter() {
+                       if idx < min {
+                               min = idx;
+                       }
+               }
+               min
+       }
+
+       #[inline]
+       fn check_spend_transaction(&self, tx: &Transaction, height: u32) -> Vec<Transaction> {
+               // Most secp and related errors trying to create keys means we have no hope of constructing
+               // a spend transaction...so we return no transactions to broadcast
+               macro_rules! ignore_error {
+                       ( $thing : expr ) => {
+                               match $thing {
+                                       Ok(a) => a,
+                                       Err(_) => return Vec::new()
+                               }
+                       };
+               }
+
+               let mut txn_to_broadcast = Vec::new();
+
+               let commitment_number = (((tx.input[0].sequence as u64 & 0xffffff) << 3*8) | (tx.lock_time as u64 & 0xffffff)) ^ self.commitment_transaction_number_obscure_factor;
+               if commitment_number >= self.get_min_seen_secret() {
+                       let secret = self.get_secret(commitment_number).unwrap();
+                       let per_commitment_key = ignore_error!(SecretKey::from_slice(&self.secp_ctx, &secret));
+                       let revocation_pubkey = match self.revocation_base_key {
+                               RevocationStorage::PrivMode { ref revocation_base_key } => {
+                                       ignore_error!(chan_utils::derive_public_revocation_key(&self.secp_ctx, &ignore_error!(PublicKey::from_secret_key(&self.secp_ctx, &per_commitment_key)), &ignore_error!(PublicKey::from_secret_key(&self.secp_ctx, &revocation_base_key))))
+                               },
+                               RevocationStorage::SigsMode { ref revocation_base_key, .. } => {
+                                       ignore_error!(chan_utils::derive_public_revocation_key(&self.secp_ctx, &ignore_error!(PublicKey::from_secret_key(&self.secp_ctx, &per_commitment_key)), &revocation_base_key))
+                               },
+                       };
+                       let delayed_key = ignore_error!(chan_utils::derive_public_key(&self.secp_ctx, &ignore_error!(PublicKey::from_secret_key(&self.secp_ctx, &per_commitment_key)), &self.delayed_payment_base_key));
+                       let a_htlc_key = ignore_error!(chan_utils::derive_public_key(&self.secp_ctx, &ignore_error!(PublicKey::from_secret_key(&self.secp_ctx, &per_commitment_key)), &self.htlc_base_key));
+                       let b_htlc_key = match self.their_htlc_base_key {
+                               None => return Vec::new(),
+                               Some(their_htlc_base_key) => ignore_error!(chan_utils::derive_public_key(&self.secp_ctx, &ignore_error!(PublicKey::from_secret_key(&self.secp_ctx, &per_commitment_key)), &their_htlc_base_key)),
+                       };
+
+                       let revokeable_redeemscript = chan_utils::get_revokeable_redeemscript(&revocation_pubkey, self.to_self_delay, &delayed_key);
+
+                       let commitment_txid = tx.txid();
+
+                       let mut total_value = 0;
+                       let mut values = Vec::new();
+                       let inputs = match self.claimable_outpoints.get(&commitment_txid) {
+                               Some(per_commitment_data) => {
+                                       let mut inp = Vec::with_capacity(per_commitment_data.htlcs.len() + 1);
+
+                                       if per_commitment_data.revoked_output_index as usize >= tx.output.len() || tx.output[per_commitment_data.revoked_output_index as usize].script_pubkey != revokeable_redeemscript.to_v0_p2wsh() {
+                                               return Vec::new(); // Corrupted per_commitment_data, not much we can do
+                                       }
+
+                                       inp.push(TxIn {
+                                               prev_hash: commitment_txid,
+                                               prev_index: per_commitment_data.revoked_output_index,
+                                               script_sig: Script::new(),
+                                               sequence: 0xffffffff,
+                                       });
+                                       values.push(tx.output[per_commitment_data.revoked_output_index as usize].value);
+                                       total_value += tx.output[per_commitment_data.revoked_output_index as usize].value;
+
+                                       for &(ref htlc, ref _next_tx_sig) in per_commitment_data.htlcs.iter() {
+                                               let expected_script = chan_utils::get_htlc_redeemscript_with_explicit_keys(&htlc, &a_htlc_key, &b_htlc_key, &revocation_pubkey, htlc.offered);
+                                               if htlc.transaction_output_index as usize >= tx.output.len() ||
+                                                               tx.output[htlc.transaction_output_index as usize].value != htlc.amount_msat / 1000 ||
+                                                               tx.output[htlc.transaction_output_index as usize].script_pubkey != expected_script.to_v0_p2wsh() {
+                                                       return Vec::new(); // Corrupted per_commitment_data, fuck this user
+                                               }
+                                               if htlc.cltv_expiry > height + CLTV_CLAIM_BUFFER {
+                                                       inp.push(TxIn {
+                                                               prev_hash: commitment_txid,
+                                                               prev_index: htlc.transaction_output_index,
+                                                               script_sig: Script::new(),
+                                                               sequence: 0xffffffff,
+                                                       });
+                                                       values.push(tx.output[htlc.transaction_output_index as usize].value);
+                                                       total_value += htlc.amount_msat / 1000;
+                                               } else {
+                                                       //TODO: Mark as "bad"
+                                                       //then broadcast using next_tx_sig
+                                               }
+                                       }
+                                       inp
+                               }, None => {
+                                       let mut inp = Vec::new(); // This is unlikely to succeed
+                                       for (idx, outp) in tx.output.iter().enumerate() {
+                                               if outp.script_pubkey == revokeable_redeemscript.to_v0_p2wsh() {
+                                                       inp.push(TxIn {
+                                                               prev_hash: commitment_txid,
+                                                               prev_index: idx as u32,
+                                                               script_sig: Script::new(),
+                                                               sequence: 0xffffffff,
+                                                       });
+                                                       values.push(outp.value);
+                                                       total_value += outp.value;
+                                                       break; // There can only be one of these
+                                               }
+                                       }
+                                       if inp.is_empty() { return Vec::new(); } // Nothing to be done...probably a false positive
+                                       inp
+                               }
+                       };
+
+                       let outputs = vec!(TxOut {
+                               script_pubkey: self.destination_script.clone(),
+                               value: total_value, //TODO: - fee
+                       });
+                       let mut spend_tx = Transaction {
+                               version: 2,
+                               lock_time: 0,
+                               input: inputs,
+                               output: outputs,
+                               witness: Vec::new(),
+                       };
+
+                       let mut values_drain = values.drain(..);
+
+                       // First input is the generic revokeable_redeemscript
+                       // TODO: Make one SighashComponents and use that throughout instead of re-building it
+                       // each time.
+                       {
+                               let sig = match self.revocation_base_key {
+                                       RevocationStorage::PrivMode { ref revocation_base_key } => {
+                                               let sighash = ignore_error!(Message::from_slice(&bip143::SighashComponents::new(&spend_tx).sighash_all(&spend_tx, 0, &revokeable_redeemscript, values_drain.next().unwrap())[..]));
+                                               let revocation_key = ignore_error!(chan_utils::derive_private_revocation_key(&self.secp_ctx, &per_commitment_key, &revocation_base_key));
+                                               ignore_error!(self.secp_ctx.sign(&sighash, &revocation_key))
+                                       },
+                                       RevocationStorage::SigsMode { .. } => {
+                                               unimplemented!();
+                                       }
+                               };
+
+                               spend_tx.witness.push(Vec::new());
+                               spend_tx.witness[0].push(sig.serialize_der(&self.secp_ctx).to_vec());
+                               spend_tx.witness[0][0].push(SigHashType::All as u8);
+                               spend_tx.witness[0].push(vec!(1)); // First if branch is revocation_key
+                       }
+
+                       match self.claimable_outpoints.get(&commitment_txid) {
+                               None => {},
+                               Some(per_commitment_data) => {
+                                       let mut htlc_idx = 0;
+                                       for (idx, _) in spend_tx.input.iter().enumerate() {
+                                               if idx == 0 { continue; } // We already signed the first input
+
+                                               let mut htlc;
+                                               while {
+                                                       htlc = &per_commitment_data.htlcs[htlc_idx].0;
+                                                       htlc_idx += 1;
+                                                       htlc.cltv_expiry > height + CLTV_CLAIM_BUFFER
+                                               } {}
+
+                                               let sig = match self.revocation_base_key {
+                                                       RevocationStorage::PrivMode { ref revocation_base_key } => {
+                                                               let htlc_redeemscript = chan_utils::get_htlc_redeemscript_with_explicit_keys(htlc, &a_htlc_key, &b_htlc_key, &revocation_pubkey, htlc.offered);
+                                                               let sighash = ignore_error!(Message::from_slice(&bip143::SighashComponents::new(&spend_tx).sighash_all(&spend_tx, idx, &htlc_redeemscript, values_drain.next().unwrap())[..]));
+
+                                                               let revocation_key = ignore_error!(chan_utils::derive_private_revocation_key(&self.secp_ctx, &per_commitment_key, &revocation_base_key));
+                                                               ignore_error!(self.secp_ctx.sign(&sighash, &revocation_key))
+                                                       },
+                                                       RevocationStorage::SigsMode { .. } => {
+                                                               unimplemented!();
+                                                       }
+                                               };
+
+                                               spend_tx.witness.push(Vec::new());
+                                               spend_tx.witness[0].push(revocation_pubkey.serialize().to_vec()); // First if branch is revocation_key
+                                               spend_tx.witness[0].push(sig.serialize_der(&self.secp_ctx).to_vec());
+                                               spend_tx.witness[0][0].push(SigHashType::All as u8);
+                                       }
+                               }
+                       }
+
+                       txn_to_broadcast.push(spend_tx);
+               }
+
+               txn_to_broadcast
+       }
+
+       fn block_connected(&self, txn_matched: &[&Transaction], height: u32, chain_monitor: &ChainWatchInterface) {
+               for tx in txn_matched {
+                       if tx.input.len() != 1 {
+                               // We currently only ever sign something spending a commitment or HTLC
+                               // transaction with 1 input, so we can skip most transactions trivially.
+                               continue;
+                       }
+
+                       for txin in tx.input.iter() {
+                               if self.funding_txo.is_none() || (txin.prev_hash == self.funding_txo.unwrap().0 && txin.prev_index == self.funding_txo.unwrap().1 as u32) {
+                                       for tx in self.check_spend_transaction(tx, height).iter() {
+                                               chain_monitor.broadcast_transaction(tx);
+                                       }
+                               }
+                       }
+               }
+       }
+}
+
+#[cfg(test)]
+mod tests {
+       use bitcoin::util::misc::hex_bytes;
+       use bitcoin::blockdata::script::Script;
+       use ln::channelmonitor::ChannelMonitor;
+       use secp256k1::key::{SecretKey,PublicKey};
+       use secp256k1::Secp256k1;
+
+       #[test]
+       fn test_per_commitment_storage() {
+               // Test vectors from BOLT 3:
+               let mut secrets: Vec<[u8; 32]> = Vec::new();
+               let mut monitor: ChannelMonitor;
+               let secp_ctx = Secp256k1::new();
+
+               macro_rules! test_secrets {
+                       () => {
+                               let mut idx = 281474976710655;
+                               for secret in secrets.iter() {
+                                       assert_eq!(monitor.get_secret(idx).unwrap(), *secret);
+                                       idx -= 1;
+                               }
+                               assert_eq!(monitor.get_min_seen_secret(), idx + 1);
+                               assert!(monitor.get_secret(idx).is_err());
+                       };
+               }
+
+               {
+                       // insert_secret correct sequence
+                       monitor = ChannelMonitor::new(&SecretKey::from_slice(&secp_ctx, &[42; 32]).unwrap(), &PublicKey::new(), &PublicKey::new(), 0, Script::new());
+                       secrets.clear();
+
+                       secrets.push([0; 32]);
+                       secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc").unwrap());
+                       monitor.provide_secret(281474976710655, secrets.last().unwrap().clone()).unwrap();
+                       test_secrets!();
+
+                       secrets.push([0; 32]);
+                       secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("c7518c8ae4660ed02894df8976fa1a3659c1a8b4b5bec0c4b872abeba4cb8964").unwrap());
+                       monitor.provide_secret(281474976710654, secrets.last().unwrap().clone()).unwrap();
+                       test_secrets!();
+
+                       secrets.push([0; 32]);
+                       secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8").unwrap());
+                       monitor.provide_secret(281474976710653, secrets.last().unwrap().clone()).unwrap();
+                       test_secrets!();
+
+                       secrets.push([0; 32]);
+                       secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116").unwrap());
+                       monitor.provide_secret(281474976710652, secrets.last().unwrap().clone()).unwrap();
+                       test_secrets!();
+
+                       secrets.push([0; 32]);
+                       secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("c65716add7aa98ba7acb236352d665cab17345fe45b55fb879ff80e6bd0c41dd").unwrap());
+                       monitor.provide_secret(281474976710651, secrets.last().unwrap().clone()).unwrap();
+                       test_secrets!();
+
+                       secrets.push([0; 32]);
+                       secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("969660042a28f32d9be17344e09374b379962d03db1574df5a8a5a47e19ce3f2").unwrap());
+                       monitor.provide_secret(281474976710650, secrets.last().unwrap().clone()).unwrap();
+                       test_secrets!();
+
+                       secrets.push([0; 32]);
+                       secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("a5a64476122ca0925fb344bdc1854c1c0a59fc614298e50a33e331980a220f32").unwrap());
+                       monitor.provide_secret(281474976710649, secrets.last().unwrap().clone()).unwrap();
+                       test_secrets!();
+
+                       secrets.push([0; 32]);
+                       secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("05cde6323d949933f7f7b78776bcc1ea6d9b31447732e3802e1f7ac44b650e17").unwrap());
+                       monitor.provide_secret(281474976710648, secrets.last().unwrap().clone()).unwrap();
+                       test_secrets!();
+               }
+
+               {
+                       // insert_secret #1 incorrect
+                       monitor = ChannelMonitor::new(&SecretKey::from_slice(&secp_ctx, &[42; 32]).unwrap(), &PublicKey::new(), &PublicKey::new(), 0, Script::new());
+                       secrets.clear();
+
+                       secrets.push([0; 32]);
+                       secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("02a40c85b6f28da08dfdbe0926c53fab2de6d28c10301f8f7c4073d5e42e3148").unwrap());
+                       monitor.provide_secret(281474976710655, secrets.last().unwrap().clone()).unwrap();
+                       test_secrets!();
+
+                       secrets.push([0; 32]);
+                       secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("c7518c8ae4660ed02894df8976fa1a3659c1a8b4b5bec0c4b872abeba4cb8964").unwrap());
+                       assert_eq!(monitor.provide_secret(281474976710654, secrets.last().unwrap().clone()).unwrap_err().err,
+                                       "Previous secret did not match new one");
+               }
+
+               {
+                       // insert_secret #2 incorrect (#1 derived from incorrect)
+                       monitor = ChannelMonitor::new(&SecretKey::from_slice(&secp_ctx, &[42; 32]).unwrap(), &PublicKey::new(), &PublicKey::new(), 0, Script::new());
+                       secrets.clear();
+
+                       secrets.push([0; 32]);
+                       secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("02a40c85b6f28da08dfdbe0926c53fab2de6d28c10301f8f7c4073d5e42e3148").unwrap());
+                       monitor.provide_secret(281474976710655, secrets.last().unwrap().clone()).unwrap();
+                       test_secrets!();
+
+                       secrets.push([0; 32]);
+                       secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("dddc3a8d14fddf2b68fa8c7fbad2748274937479dd0f8930d5ebb4ab6bd866a3").unwrap());
+                       monitor.provide_secret(281474976710654, secrets.last().unwrap().clone()).unwrap();
+                       test_secrets!();
+
+                       secrets.push([0; 32]);
+                       secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8").unwrap());
+                       monitor.provide_secret(281474976710653, secrets.last().unwrap().clone()).unwrap();
+                       test_secrets!();
+
+                       secrets.push([0; 32]);
+                       secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116").unwrap());
+                       assert_eq!(monitor.provide_secret(281474976710652, secrets.last().unwrap().clone()).unwrap_err().err,
+                                       "Previous secret did not match new one");
+               }
+
+               {
+                       // insert_secret #3 incorrect
+                       monitor = ChannelMonitor::new(&SecretKey::from_slice(&secp_ctx, &[42; 32]).unwrap(), &PublicKey::new(), &PublicKey::new(), 0, Script::new());
+                       secrets.clear();
+
+                       secrets.push([0; 32]);
+                       secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc").unwrap());
+                       monitor.provide_secret(281474976710655, secrets.last().unwrap().clone()).unwrap();
+                       test_secrets!();
+
+                       secrets.push([0; 32]);
+                       secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("c7518c8ae4660ed02894df8976fa1a3659c1a8b4b5bec0c4b872abeba4cb8964").unwrap());
+                       monitor.provide_secret(281474976710654, secrets.last().unwrap().clone()).unwrap();
+                       test_secrets!();
+
+                       secrets.push([0; 32]);
+                       secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("c51a18b13e8527e579ec56365482c62f180b7d5760b46e9477dae59e87ed423a").unwrap());
+                       monitor.provide_secret(281474976710653, secrets.last().unwrap().clone()).unwrap();
+                       test_secrets!();
+
+                       secrets.push([0; 32]);
+                       secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116").unwrap());
+                       assert_eq!(monitor.provide_secret(281474976710652, secrets.last().unwrap().clone()).unwrap_err().err,
+                                       "Previous secret did not match new one");
+               }
+
+               {
+                       // insert_secret #4 incorrect (1,2,3 derived from incorrect)
+                       monitor = ChannelMonitor::new(&SecretKey::from_slice(&secp_ctx, &[42; 32]).unwrap(), &PublicKey::new(), &PublicKey::new(), 0, Script::new());
+                       secrets.clear();
+
+                       secrets.push([0; 32]);
+                       secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("02a40c85b6f28da08dfdbe0926c53fab2de6d28c10301f8f7c4073d5e42e3148").unwrap());
+                       monitor.provide_secret(281474976710655, secrets.last().unwrap().clone()).unwrap();
+                       test_secrets!();
+
+                       secrets.push([0; 32]);
+                       secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("dddc3a8d14fddf2b68fa8c7fbad2748274937479dd0f8930d5ebb4ab6bd866a3").unwrap());
+                       monitor.provide_secret(281474976710654, secrets.last().unwrap().clone()).unwrap();
+                       test_secrets!();
+
+                       secrets.push([0; 32]);
+                       secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("c51a18b13e8527e579ec56365482c62f180b7d5760b46e9477dae59e87ed423a").unwrap());
+                       monitor.provide_secret(281474976710653, secrets.last().unwrap().clone()).unwrap();
+                       test_secrets!();
+
+                       secrets.push([0; 32]);
+                       secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("ba65d7b0ef55a3ba300d4e87af29868f394f8f138d78a7011669c79b37b936f4").unwrap());
+                       monitor.provide_secret(281474976710652, secrets.last().unwrap().clone()).unwrap();
+                       test_secrets!();
+
+                       secrets.push([0; 32]);
+                       secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("c65716add7aa98ba7acb236352d665cab17345fe45b55fb879ff80e6bd0c41dd").unwrap());
+                       monitor.provide_secret(281474976710651, secrets.last().unwrap().clone()).unwrap();
+                       test_secrets!();
+
+                       secrets.push([0; 32]);
+                       secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("969660042a28f32d9be17344e09374b379962d03db1574df5a8a5a47e19ce3f2").unwrap());
+                       monitor.provide_secret(281474976710650, secrets.last().unwrap().clone()).unwrap();
+                       test_secrets!();
+
+                       secrets.push([0; 32]);
+                       secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("a5a64476122ca0925fb344bdc1854c1c0a59fc614298e50a33e331980a220f32").unwrap());
+                       monitor.provide_secret(281474976710649, secrets.last().unwrap().clone()).unwrap();
+                       test_secrets!();
+
+                       secrets.push([0; 32]);
+                       secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("05cde6323d949933f7f7b78776bcc1ea6d9b31447732e3802e1f7ac44b650e17").unwrap());
+                       assert_eq!(monitor.provide_secret(281474976710648, secrets.last().unwrap().clone()).unwrap_err().err,
+                                       "Previous secret did not match new one");
+               }
+
+               {
+                       // insert_secret #5 incorrect
+                       monitor = ChannelMonitor::new(&SecretKey::from_slice(&secp_ctx, &[42; 32]).unwrap(), &PublicKey::new(), &PublicKey::new(), 0, Script::new());
+                       secrets.clear();
+
+                       secrets.push([0; 32]);
+                       secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc").unwrap());
+                       monitor.provide_secret(281474976710655, secrets.last().unwrap().clone()).unwrap();
+                       test_secrets!();
+
+                       secrets.push([0; 32]);
+                       secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("c7518c8ae4660ed02894df8976fa1a3659c1a8b4b5bec0c4b872abeba4cb8964").unwrap());
+                       monitor.provide_secret(281474976710654, secrets.last().unwrap().clone()).unwrap();
+                       test_secrets!();
+
+                       secrets.push([0; 32]);
+                       secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8").unwrap());
+                       monitor.provide_secret(281474976710653, secrets.last().unwrap().clone()).unwrap();
+                       test_secrets!();
+
+                       secrets.push([0; 32]);
+                       secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116").unwrap());
+                       monitor.provide_secret(281474976710652, secrets.last().unwrap().clone()).unwrap();
+                       test_secrets!();
+
+                       secrets.push([0; 32]);
+                       secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("631373ad5f9ef654bb3dade742d09504c567edd24320d2fcd68e3cc47e2ff6a6").unwrap());
+                       monitor.provide_secret(281474976710651, secrets.last().unwrap().clone()).unwrap();
+                       test_secrets!();
+
+                       secrets.push([0; 32]);
+                       secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("969660042a28f32d9be17344e09374b379962d03db1574df5a8a5a47e19ce3f2").unwrap());
+                       assert_eq!(monitor.provide_secret(281474976710650, secrets.last().unwrap().clone()).unwrap_err().err,
+                                       "Previous secret did not match new one");
+               }
+
+               {
+                       // insert_secret #6 incorrect (5 derived from incorrect)
+                       monitor = ChannelMonitor::new(&SecretKey::from_slice(&secp_ctx, &[42; 32]).unwrap(), &PublicKey::new(), &PublicKey::new(), 0, Script::new());
+                       secrets.clear();
+
+                       secrets.push([0; 32]);
+                       secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc").unwrap());
+                       monitor.provide_secret(281474976710655, secrets.last().unwrap().clone()).unwrap();
+                       test_secrets!();
+
+                       secrets.push([0; 32]);
+                       secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("c7518c8ae4660ed02894df8976fa1a3659c1a8b4b5bec0c4b872abeba4cb8964").unwrap());
+                       monitor.provide_secret(281474976710654, secrets.last().unwrap().clone()).unwrap();
+                       test_secrets!();
+
+                       secrets.push([0; 32]);
+                       secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8").unwrap());
+                       monitor.provide_secret(281474976710653, secrets.last().unwrap().clone()).unwrap();
+                       test_secrets!();
+
+                       secrets.push([0; 32]);
+                       secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116").unwrap());
+                       monitor.provide_secret(281474976710652, secrets.last().unwrap().clone()).unwrap();
+                       test_secrets!();
+
+                       secrets.push([0; 32]);
+                       secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("631373ad5f9ef654bb3dade742d09504c567edd24320d2fcd68e3cc47e2ff6a6").unwrap());
+                       monitor.provide_secret(281474976710651, secrets.last().unwrap().clone()).unwrap();
+                       test_secrets!();
+
+                       secrets.push([0; 32]);
+                       secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("b7e76a83668bde38b373970155c868a653304308f9896692f904a23731224bb1").unwrap());
+                       monitor.provide_secret(281474976710650, secrets.last().unwrap().clone()).unwrap();
+                       test_secrets!();
+
+                       secrets.push([0; 32]);
+                       secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("a5a64476122ca0925fb344bdc1854c1c0a59fc614298e50a33e331980a220f32").unwrap());
+                       monitor.provide_secret(281474976710649, secrets.last().unwrap().clone()).unwrap();
+                       test_secrets!();
+
+                       secrets.push([0; 32]);
+                       secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("05cde6323d949933f7f7b78776bcc1ea6d9b31447732e3802e1f7ac44b650e17").unwrap());
+                       assert_eq!(monitor.provide_secret(281474976710648, secrets.last().unwrap().clone()).unwrap_err().err,
+                                       "Previous secret did not match new one");
+               }
+
+               {
+                       // insert_secret #7 incorrect
+                       monitor = ChannelMonitor::new(&SecretKey::from_slice(&secp_ctx, &[42; 32]).unwrap(), &PublicKey::new(), &PublicKey::new(), 0, Script::new());
+                       secrets.clear();
+
+                       secrets.push([0; 32]);
+                       secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc").unwrap());
+                       monitor.provide_secret(281474976710655, secrets.last().unwrap().clone()).unwrap();
+                       test_secrets!();
+
+                       secrets.push([0; 32]);
+                       secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("c7518c8ae4660ed02894df8976fa1a3659c1a8b4b5bec0c4b872abeba4cb8964").unwrap());
+                       monitor.provide_secret(281474976710654, secrets.last().unwrap().clone()).unwrap();
+                       test_secrets!();
+
+                       secrets.push([0; 32]);
+                       secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8").unwrap());
+                       monitor.provide_secret(281474976710653, secrets.last().unwrap().clone()).unwrap();
+                       test_secrets!();
+
+                       secrets.push([0; 32]);
+                       secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116").unwrap());
+                       monitor.provide_secret(281474976710652, secrets.last().unwrap().clone()).unwrap();
+                       test_secrets!();
+
+                       secrets.push([0; 32]);
+                       secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("c65716add7aa98ba7acb236352d665cab17345fe45b55fb879ff80e6bd0c41dd").unwrap());
+                       monitor.provide_secret(281474976710651, secrets.last().unwrap().clone()).unwrap();
+                       test_secrets!();
+
+                       secrets.push([0; 32]);
+                       secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("969660042a28f32d9be17344e09374b379962d03db1574df5a8a5a47e19ce3f2").unwrap());
+                       monitor.provide_secret(281474976710650, secrets.last().unwrap().clone()).unwrap();
+                       test_secrets!();
+
+                       secrets.push([0; 32]);
+                       secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("e7971de736e01da8ed58b94c2fc216cb1dca9e326f3a96e7194fe8ea8af6c0a3").unwrap());
+                       monitor.provide_secret(281474976710649, secrets.last().unwrap().clone()).unwrap();
+                       test_secrets!();
+
+                       secrets.push([0; 32]);
+                       secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("05cde6323d949933f7f7b78776bcc1ea6d9b31447732e3802e1f7ac44b650e17").unwrap());
+                       assert_eq!(monitor.provide_secret(281474976710648, secrets.last().unwrap().clone()).unwrap_err().err,
+                                       "Previous secret did not match new one");
+               }
+
+               {
+                       // insert_secret #8 incorrect
+                       monitor = ChannelMonitor::new(&SecretKey::from_slice(&secp_ctx, &[42; 32]).unwrap(), &PublicKey::new(), &PublicKey::new(), 0, Script::new());
+                       secrets.clear();
+
+                       secrets.push([0; 32]);
+                       secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc").unwrap());
+                       monitor.provide_secret(281474976710655, secrets.last().unwrap().clone()).unwrap();
+                       test_secrets!();
+
+                       secrets.push([0; 32]);
+                       secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("c7518c8ae4660ed02894df8976fa1a3659c1a8b4b5bec0c4b872abeba4cb8964").unwrap());
+                       monitor.provide_secret(281474976710654, secrets.last().unwrap().clone()).unwrap();
+                       test_secrets!();
+
+                       secrets.push([0; 32]);
+                       secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8").unwrap());
+                       monitor.provide_secret(281474976710653, secrets.last().unwrap().clone()).unwrap();
+                       test_secrets!();
+
+                       secrets.push([0; 32]);
+                       secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116").unwrap());
+                       monitor.provide_secret(281474976710652, secrets.last().unwrap().clone()).unwrap();
+                       test_secrets!();
+
+                       secrets.push([0; 32]);
+                       secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("c65716add7aa98ba7acb236352d665cab17345fe45b55fb879ff80e6bd0c41dd").unwrap());
+                       monitor.provide_secret(281474976710651, secrets.last().unwrap().clone()).unwrap();
+                       test_secrets!();
+
+                       secrets.push([0; 32]);
+                       secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("969660042a28f32d9be17344e09374b379962d03db1574df5a8a5a47e19ce3f2").unwrap());
+                       monitor.provide_secret(281474976710650, secrets.last().unwrap().clone()).unwrap();
+                       test_secrets!();
+
+                       secrets.push([0; 32]);
+                       secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("a5a64476122ca0925fb344bdc1854c1c0a59fc614298e50a33e331980a220f32").unwrap());
+                       monitor.provide_secret(281474976710649, secrets.last().unwrap().clone()).unwrap();
+                       test_secrets!();
+
+                       secrets.push([0; 32]);
+                       secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex_bytes("a7efbc61aac46d34f77778bac22c8a20c6a46ca460addc49009bda875ec88fa4").unwrap());
+                       assert_eq!(monitor.provide_secret(281474976710648, secrets.last().unwrap().clone()).unwrap_err().err,
+                                       "Previous secret did not match new one");
+               }
+       }
+}
diff --git a/src/ln/mod.rs b/src/ln/mod.rs
new file mode 100644 (file)
index 0000000..1f5fa46
--- /dev/null
@@ -0,0 +1,9 @@
+pub mod channelmanager;
+pub mod channel;
+pub mod channelmonitor;
+pub mod msgs;
+pub mod router;
+pub mod peer_channel_encryptor;
+pub mod peer_handler;
+
+mod chan_utils;
diff --git a/src/ln/msgs.rs b/src/ln/msgs.rs
new file mode 100644 (file)
index 0000000..520fe5f
--- /dev/null
@@ -0,0 +1,934 @@
+use secp256k1::key::PublicKey;
+use secp256k1::{Secp256k1, Signature};
+use bitcoin::util::uint::Uint256;
+use bitcoin::util::hash::Sha256dHash;
+use bitcoin::network::serialize::deserialize;
+use bitcoin::blockdata::script::Script;
+
+use std::error::Error;
+use std::fmt;
+use std::result::Result;
+
+use util::{byte_utils, internal_traits, events};
+
+pub trait MsgEncodable {
+       fn encode(&self) -> Vec<u8>;
+}
+#[derive(Debug)]
+pub enum DecodeError {
+       /// Unknown realm byte in an OnionHopData packet
+       UnknownRealmByte,
+       /// Failed to decode a public key (ie it's invalid)
+       BadPublicKey,
+       /// Buffer not of right length (either too short or too long)
+       WrongLength,
+}
+pub trait MsgDecodable: Sized {
+       fn decode(v: &[u8]) -> Result<Self, DecodeError>;
+}
+
+/// Tracks localfeatures which are only in init messages
+#[derive(Clone, PartialEq)]
+pub struct LocalFeatures {
+       flags: Vec<u8>,
+}
+
+impl LocalFeatures {
+       pub fn new() -> LocalFeatures {
+               LocalFeatures {
+                       flags: Vec::new(),
+               }
+       }
+
+       pub fn supports_data_loss_protect(&self) -> bool {
+               self.flags.len() > 0 && (self.flags[0] & 3) != 0
+       }
+       pub fn requires_data_loss_protect(&self) -> bool {
+               self.flags.len() > 0 && (self.flags[0] & 1) != 0
+       }
+
+       pub fn supports_initial_routing_sync(&self) -> bool {
+               self.flags.len() > 0 && (self.flags[0] & (1 << 3)) != 0
+       }
+
+       pub fn supports_upfront_shutdown_script(&self) -> bool {
+               self.flags.len() > 0 && (self.flags[0] & (3 << 4)) != 0
+       }
+       pub fn requires_upfront_shutdown_script(&self) -> bool {
+               self.flags.len() > 0 && (self.flags[0] & (1 << 4)) != 0
+       }
+
+       pub fn requires_unknown_bits(&self) -> bool {
+               for (idx, &byte) in self.flags.iter().enumerate() {
+                       if idx != 0 && (byte & 0x55) != 0 {
+                               return true;
+                       } else if idx == 0 && (byte & 0x14) != 0 {
+                               return true;
+                       }
+               }
+               return false;
+       }
+
+       pub fn supports_unknown_bits(&self) -> bool {
+               for (idx, &byte) in self.flags.iter().enumerate() {
+                       if idx != 0 && byte != 0 {
+                               return true;
+                       } else if idx == 0 && (byte & 0xc4) != 0 {
+                               return true;
+                       }
+               }
+               return false;
+       }
+}
+
+/// Tracks globalfeatures which are in init messages and routing announcements
+#[derive(Clone, PartialEq)]
+pub struct GlobalFeatures {
+       flags: Vec<u8>,
+}
+
+impl GlobalFeatures {
+       pub fn new() -> GlobalFeatures {
+               GlobalFeatures {
+                       flags: Vec::new(),
+               }
+       }
+
+       pub fn requires_unknown_bits(&self) -> bool {
+               for &byte in self.flags.iter() {
+                       if (byte & 0x55) != 0 {
+                               return true;
+                       }
+               }
+               return false;
+       }
+
+       pub fn supports_unknown_bits(&self) -> bool {
+               for &byte in self.flags.iter() {
+                       if byte != 0 {
+                               return true;
+                       }
+               }
+               return false;
+       }
+}
+
+pub struct Init {
+       pub global_features: GlobalFeatures,
+       pub local_features: LocalFeatures,
+}
+
+pub struct OpenChannel {
+       pub chain_hash: Sha256dHash,
+       pub temporary_channel_id: Uint256,
+       pub funding_satoshis: u64,
+       pub push_msat: u64,
+       pub dust_limit_satoshis: u64,
+       pub max_htlc_value_in_flight_msat: u64,
+       pub channel_reserve_satoshis: u64,
+       pub htlc_minimum_msat: u64,
+       pub feerate_per_kw: u32,
+       pub to_self_delay: u16,
+       pub max_accepted_htlcs: u16,
+       pub funding_pubkey: PublicKey,
+       pub revocation_basepoint: PublicKey,
+       pub payment_basepoint: PublicKey,
+       pub delayed_payment_basepoint: PublicKey,
+       pub htlc_basepoint: PublicKey,
+       pub first_per_commitment_point: PublicKey,
+       pub channel_flags: u8,
+       pub shutdown_scriptpubkey: Option<Script>,
+}
+
+pub struct AcceptChannel {
+       pub temporary_channel_id: Uint256,
+       pub dust_limit_satoshis: u64,
+       pub max_htlc_value_in_flight_msat: u64,
+       pub channel_reserve_satoshis: u64,
+       pub htlc_minimum_msat: u64,
+       pub minimum_depth: u32,
+       pub to_self_delay: u16,
+       pub max_accepted_htlcs: u16,
+       pub funding_pubkey: PublicKey,
+       pub revocation_basepoint: PublicKey,
+       pub payment_basepoint: PublicKey,
+       pub delayed_payment_basepoint: PublicKey,
+       pub htlc_basepoint: PublicKey,
+       pub first_per_commitment_point: PublicKey,
+       pub shutdown_scriptpubkey: Option<Script>,
+}
+
+pub struct FundingCreated {
+       pub temporary_channel_id: Uint256,
+       pub funding_txid: Sha256dHash,
+       pub funding_output_index: u16,
+       pub signature: Signature,
+}
+
+pub struct FundingSigned {
+       pub channel_id: Uint256,
+       pub signature: Signature,
+}
+
+pub struct FundingLocked {
+       pub channel_id: Uint256,
+       pub next_per_commitment_point: PublicKey,
+}
+
+pub struct Shutdown {
+       pub channel_id: Uint256,
+       pub scriptpubkey: Script,
+}
+
+pub struct ClosingSigned {
+       pub channel_id: Uint256,
+       pub fee_satoshis: u64,
+       pub signature: Signature,
+}
+
+#[derive(Clone)]
+pub struct UpdateAddHTLC {
+       pub channel_id: Uint256,
+       pub htlc_id: u64,
+       pub amount_msat: u64,
+       pub payment_hash: [u8; 32],
+       pub cltv_expiry: u32,
+       pub onion_routing_packet: OnionPacket,
+}
+
+#[derive(Clone)]
+pub struct UpdateFulfillHTLC {
+       pub channel_id: Uint256,
+       pub htlc_id: u64,
+       pub payment_preimage: [u8; 32],
+}
+
+pub struct UpdateFailHTLC {
+       pub channel_id: Uint256,
+       pub htlc_id: u64,
+       pub reason: OnionErrorPacket,
+}
+
+pub struct UpdateFailMalformedHTLC {
+       pub channel_id: Uint256,
+       pub htlc_id: u64,
+       pub sha256_of_onion: [u8; 32],
+       pub failure_code: u16,
+}
+
+#[derive(Clone)]
+pub struct CommitmentSigned {
+       pub channel_id: Uint256,
+       pub signature: Signature,
+       pub htlc_signatures: Vec<Signature>,
+}
+
+pub struct RevokeAndACK {
+       pub channel_id: Uint256,
+       pub per_commitment_secret: [u8; 32],
+       pub next_per_commitment_point: PublicKey,
+}
+
+pub struct UpdateFee {
+       pub channel_id: Uint256,
+       pub feerate_per_kw: u32,
+}
+
+pub struct ChannelReestablish {
+       pub channel_id: Uint256,
+       pub next_local_commitment_number: u64,
+       pub next_remote_commitment_number: u64,
+       pub your_last_per_commitment_secret: Option<[u8; 32]>,
+       pub my_current_per_commitment_point: PublicKey,
+}
+
+#[derive(Clone)]
+pub struct AnnouncementSignatures {
+       pub channel_id: Uint256,
+       pub short_channel_id: u64,
+       pub node_signature: Signature,
+       pub bitcoin_signature: Signature,
+}
+
+#[derive(Clone)]
+pub enum NetAddress {
+       Dummy,
+       IPv4 {
+               addr: [u8; 4],
+               port: u16,
+       },
+       IPv6 {
+               addr: [u8; 16],
+               port: u16,
+       },
+       OnionV2 {
+               addr: [u8; 10],
+               port: u16,
+       },
+       OnionV3 {
+               ed25519_pubkey: [u8; 32],
+               checksum: u16,
+               version: u8,
+               //TODO: Do we need a port number here???
+       },
+}
+
+pub struct UnsignedNodeAnnouncement {
+       pub features: GlobalFeatures,
+       pub timestamp: u32,
+       pub node_id: PublicKey,
+       pub rgb: [u8; 3],
+       pub alias: [u8; 32],
+       pub addresses: Vec<NetAddress>,
+}
+pub struct NodeAnnouncement {
+       pub signature: Signature,
+       pub contents: UnsignedNodeAnnouncement,
+}
+
+#[derive(PartialEq, Clone)]
+pub struct UnsignedChannelAnnouncement {
+       pub features: GlobalFeatures,
+       pub chain_hash: Sha256dHash,
+       pub short_channel_id: u64,
+       pub node_id_1: PublicKey,
+       pub node_id_2: PublicKey,
+       pub bitcoin_key_1: PublicKey,
+       pub bitcoin_key_2: PublicKey,
+}
+#[derive(PartialEq, Clone)]
+pub struct ChannelAnnouncement {
+       pub node_signature_1: Signature,
+       pub node_signature_2: Signature,
+       pub bitcoin_signature_1: Signature,
+       pub bitcoin_signature_2: Signature,
+       pub contents: UnsignedChannelAnnouncement,
+}
+
+#[derive(PartialEq, Clone)]
+pub struct UnsignedChannelUpdate {
+       pub chain_hash: Sha256dHash,
+       pub short_channel_id: u64,
+       pub timestamp: u32,
+       pub flags: u16,
+       pub cltv_expiry_delta: u16,
+       pub htlc_minimum_msat: u64,
+       pub fee_base_msat: u32,
+       pub fee_proportional_millionths: u32,
+}
+#[derive(PartialEq, Clone)]
+pub struct ChannelUpdate {
+       pub signature: Signature,
+       pub contents: UnsignedChannelUpdate,
+}
+
+/// Used to put an error message in a HandleError
+pub enum ErrorMessage {
+       UpdateFailHTLC {
+               msg: UpdateFailHTLC
+       },
+       DisconnectPeer {},
+}
+
+pub struct HandleError { //TODO: rename me
+       pub err: &'static str,
+       pub msg: Option<ErrorMessage>, //TODO: Move into an Action enum and require it!
+}
+
+pub trait ChannelMessageHandler : events::EventsProvider {
+       //Channel init:
+       fn handle_open_channel(&self, their_node_id: &PublicKey, msg: &OpenChannel) -> Result<AcceptChannel, HandleError>;
+       fn handle_accept_channel(&self, their_node_id: &PublicKey, msg: &AcceptChannel) -> Result<(), HandleError>;
+       fn handle_funding_created(&self, their_node_id: &PublicKey, msg: &FundingCreated) -> Result<FundingSigned, HandleError>;
+       fn handle_funding_signed(&self, their_node_id: &PublicKey, msg: &FundingSigned) -> Result<(), HandleError>;
+       fn handle_funding_locked(&self, their_node_id: &PublicKey, msg: &FundingLocked) -> Result<Option<AnnouncementSignatures>, HandleError>;
+
+       // Channl close:
+       fn handle_shutdown(&self, their_node_id: &PublicKey, msg: &Shutdown) -> Result<(), HandleError>;
+       fn handle_closing_signed(&self, their_node_id: &PublicKey, msg: &ClosingSigned) -> Result<(), HandleError>;
+
+       // HTLC handling:
+       fn handle_update_add_htlc(&self, their_node_id: &PublicKey, msg: &UpdateAddHTLC) -> Result<(), HandleError>;
+       fn handle_update_fulfill_htlc(&self, their_node_id: &PublicKey, msg: &UpdateFulfillHTLC) -> Result<Option<(Vec<UpdateAddHTLC>, CommitmentSigned)>, HandleError>;
+       fn handle_update_fail_htlc(&self, their_node_id: &PublicKey, msg: &UpdateFailHTLC) -> Result<Option<(Vec<UpdateAddHTLC>, CommitmentSigned)>, HandleError>;
+       fn handle_update_fail_malformed_htlc(&self, their_node_id: &PublicKey, msg: &UpdateFailMalformedHTLC) -> Result<Option<(Vec<UpdateAddHTLC>, CommitmentSigned)>, HandleError>;
+       fn handle_commitment_signed(&self, their_node_id: &PublicKey, msg: &CommitmentSigned) -> Result<RevokeAndACK, HandleError>;
+       fn handle_revoke_and_ack(&self, their_node_id: &PublicKey, msg: &RevokeAndACK) -> Result<(), HandleError>;
+
+       fn handle_update_fee(&self, their_node_id: &PublicKey, msg: &UpdateFee) -> Result<(), HandleError>;
+
+       // Channel-to-announce:
+       fn handle_announcement_signatures(&self, their_node_id: &PublicKey, msg: &AnnouncementSignatures) -> Result<(), HandleError>;
+}
+
+pub trait RoutingMessageHandler {
+       fn handle_node_announcement(&self, msg: &NodeAnnouncement) -> Result<(), HandleError>;
+       /// Handle a channel_announcement message, returning true if it should be forwarded on, false
+       /// or returning an Err otherwise.
+       fn handle_channel_announcement(&self, msg: &ChannelAnnouncement) -> Result<bool, HandleError>;
+       fn handle_channel_update(&self, msg: &ChannelUpdate) -> Result<(), HandleError>;
+}
+
+pub struct OnionRealm0HopData {
+       pub short_channel_id: u64,
+       pub amt_to_forward: u64,
+       pub outgoing_cltv_value: u32,
+       // 12 bytes of 0-padding
+}
+
+pub struct OnionHopData {
+       pub realm: u8,
+       pub data: OnionRealm0HopData,
+       pub hmac: [u8; 32],
+}
+unsafe impl internal_traits::NoDealloc for OnionHopData{}
+
+#[derive(Clone)]
+pub struct OnionPacket {
+       pub version: u8,
+       pub public_key: PublicKey,
+       pub hop_data: [u8; 20*65],
+       pub hmac: [u8; 32],
+}
+
+pub struct DecodedOnionErrorPacket {
+       pub hmac: [u8; 32],
+       pub failuremsg: Vec<u8>,
+       pub pad: Vec<u8>,
+}
+
+pub struct OnionErrorPacket {
+       // This really should be a constant size slice, but the spec lets these things be up to 128KB?
+       // (TODO) We limit it in decode to much lower...
+       pub data: Vec<u8>,
+}
+
+impl Error for DecodeError {
+       fn description(&self) -> &str {
+               match *self {
+                       DecodeError::UnknownRealmByte => "Unknown realm byte in Onion packet",
+                       DecodeError::BadPublicKey => "Invalid public key in packet",
+                       DecodeError::WrongLength => "Data was wrong length for packet",
+               }
+       }
+}
+impl fmt::Display for DecodeError {
+       fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+               f.write_str(self.description())
+       }
+}
+
+impl fmt::Debug for HandleError {
+       fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+               f.write_str(self.err)
+       }
+}
+
+macro_rules! secp_pubkey {
+       ( $ctx: expr, $slice: expr ) => {
+               match PublicKey::from_slice($ctx, $slice) {
+                       Ok(key) => key,
+                       Err(_) => return Err(DecodeError::BadPublicKey)
+               }
+       };
+}
+
+impl MsgDecodable for LocalFeatures {
+       fn decode(v: &[u8]) -> Result<Self, DecodeError> {
+               if v.len() < 3 { return Err(DecodeError::WrongLength); }
+               let len = byte_utils::slice_to_be16(&v[0..2]) as usize;
+               if v.len() != len + 2 { return Err(DecodeError::WrongLength); }
+               let mut flags = Vec::with_capacity(len);
+               flags.extend_from_slice(&v[2..]);
+               Ok(Self {
+                       flags: flags
+               })
+       }
+}
+impl MsgEncodable for LocalFeatures {
+       fn encode(&self) -> Vec<u8> {
+               let mut res = Vec::with_capacity(self.flags.len() + 2);
+               res.extend_from_slice(&byte_utils::be16_to_array(self.flags.len() as u16));
+               res.extend_from_slice(&self.flags[..]);
+               res
+       }
+}
+
+impl MsgDecodable for GlobalFeatures {
+       fn decode(v: &[u8]) -> Result<Self, DecodeError> {
+               if v.len() < 3 { return Err(DecodeError::WrongLength); }
+               let len = byte_utils::slice_to_be16(&v[0..2]) as usize;
+               if v.len() != len + 2 { return Err(DecodeError::WrongLength); }
+               let mut flags = Vec::with_capacity(len);
+               flags.extend_from_slice(&v[2..]);
+               Ok(Self {
+                       flags: flags
+               })
+       }
+}
+impl MsgEncodable for GlobalFeatures {
+       fn encode(&self) -> Vec<u8> {
+               let mut res = Vec::with_capacity(self.flags.len() + 2);
+               res.extend_from_slice(&byte_utils::be16_to_array(self.flags.len() as u16));
+               res.extend_from_slice(&self.flags[..]);
+               res
+       }
+}
+
+impl MsgDecodable for Init {
+       fn decode(v: &[u8]) -> Result<Self, DecodeError> {
+               let global_features = try!(GlobalFeatures::decode(v));
+               if global_features.flags.len() + 4 <= v.len() {
+                       return Err(DecodeError::WrongLength);
+               }
+               let local_features = try!(LocalFeatures::decode(&v[global_features.flags.len() + 2..]));
+               if global_features.flags.len() + local_features.flags.len() + 4 != v.len() {
+                       return Err(DecodeError::WrongLength);
+               }
+               Ok(Self {
+                       global_features: global_features,
+                       local_features: local_features,
+               })
+       }
+}
+impl MsgEncodable for Init {
+       fn encode(&self) -> Vec<u8> {
+               let mut res = Vec::with_capacity(self.global_features.flags.len() + self.local_features.flags.len());
+               res.extend_from_slice(&self.global_features.encode()[..]);
+               res.extend_from_slice(&self.local_features.encode()[..]);
+               res
+       }
+}
+
+impl MsgDecodable for OpenChannel {
+       fn decode(v: &[u8]) -> Result<Self, DecodeError> {
+               if v.len() != 2*32+6*8+4+2*2+6*33+1 {
+                       return Err(DecodeError::WrongLength);
+               }
+               let ctx = Secp256k1::without_caps();
+               let funding_pubkey = secp_pubkey!(&ctx, &v[120..153]);
+               let revocation_basepoint = secp_pubkey!(&ctx, &v[153..186]);
+               let payment_basepoint = secp_pubkey!(&ctx, &v[186..219]);
+               let delayed_payment_basepoint = secp_pubkey!(&ctx, &v[219..252]);
+               let htlc_basepoint = secp_pubkey!(&ctx, &v[252..285]);
+               let first_per_commitment_point = secp_pubkey!(&ctx, &v[285..318]);
+
+               let mut shutdown_scriptpubkey = None;
+               if v.len() >= 321 {
+                       let len = byte_utils::slice_to_be16(&v[319..321]) as usize;
+                       if v.len() != 321+len {
+                               return Err(DecodeError::WrongLength);
+                       }
+                       shutdown_scriptpubkey = Some(Script::from(v[321..321+len].to_vec()));
+               }
+
+               Ok(OpenChannel {
+                       chain_hash: deserialize(&v[0..32]).unwrap(),
+                       temporary_channel_id: deserialize(&v[32..64]).unwrap(),
+                       funding_satoshis: byte_utils::slice_to_be64(&v[64..72]),
+                       push_msat: byte_utils::slice_to_be64(&v[72..80]),
+                       dust_limit_satoshis: byte_utils::slice_to_be64(&v[80..88]),
+                       max_htlc_value_in_flight_msat: byte_utils::slice_to_be64(&v[88..96]),
+                       channel_reserve_satoshis: byte_utils::slice_to_be64(&v[96..104]),
+                       htlc_minimum_msat: byte_utils::slice_to_be64(&v[104..112]),
+                       feerate_per_kw: byte_utils::slice_to_be32(&v[112..116]),
+                       to_self_delay: byte_utils::slice_to_be16(&v[116..118]),
+                       max_accepted_htlcs: byte_utils::slice_to_be16(&v[118..120]),
+                       funding_pubkey: funding_pubkey,
+                       revocation_basepoint: revocation_basepoint,
+                       payment_basepoint: payment_basepoint,
+                       delayed_payment_basepoint: delayed_payment_basepoint,
+                       htlc_basepoint: htlc_basepoint,
+                       first_per_commitment_point: first_per_commitment_point,
+                       channel_flags: v[318],
+                       shutdown_scriptpubkey: shutdown_scriptpubkey
+               })
+       }
+}
+impl MsgEncodable for OpenChannel {
+       fn encode(&self) -> Vec<u8> {
+               unimplemented!();
+       }
+}
+
+
+impl MsgDecodable for AcceptChannel {
+       fn decode(_v: &[u8]) -> Result<Self, DecodeError> {
+               unimplemented!();
+       }
+}
+impl MsgEncodable for AcceptChannel {
+       fn encode(&self) -> Vec<u8> {
+               unimplemented!();
+       }
+}
+
+impl MsgDecodable for FundingCreated {
+       fn decode(_v: &[u8]) -> Result<Self, DecodeError> {
+               unimplemented!();
+       }
+}
+impl MsgEncodable for FundingCreated {
+       fn encode(&self) -> Vec<u8> {
+               unimplemented!();
+       }
+}
+
+impl MsgDecodable for FundingSigned {
+       fn decode(_v: &[u8]) -> Result<Self, DecodeError> {
+               unimplemented!();
+       }
+}
+impl MsgEncodable for FundingSigned {
+       fn encode(&self) -> Vec<u8> {
+               unimplemented!();
+       }
+}
+
+impl MsgDecodable for FundingLocked {
+       fn decode(_v: &[u8]) -> Result<Self, DecodeError> {
+               unimplemented!();
+       }
+}
+impl MsgEncodable for FundingLocked {
+       fn encode(&self) -> Vec<u8> {
+               unimplemented!();
+       }
+}
+
+impl MsgDecodable for Shutdown {
+       fn decode(_v: &[u8]) -> Result<Self, DecodeError> {
+               unimplemented!();
+       }
+}
+impl MsgEncodable for Shutdown {
+       fn encode(&self) -> Vec<u8> {
+               unimplemented!();
+       }
+}
+
+impl MsgDecodable for ClosingSigned {
+       fn decode(_v: &[u8]) -> Result<Self, DecodeError> {
+               unimplemented!();
+       }
+}
+impl MsgEncodable for ClosingSigned {
+       fn encode(&self) -> Vec<u8> {
+               unimplemented!();
+       }
+}
+
+impl MsgDecodable for UpdateAddHTLC {
+       fn decode(_v: &[u8]) -> Result<Self, DecodeError> {
+               unimplemented!();
+       }
+}
+impl MsgEncodable for UpdateAddHTLC {
+       fn encode(&self) -> Vec<u8> {
+               unimplemented!();
+       }
+}
+
+impl MsgDecodable for UpdateFulfillHTLC {
+       fn decode(_v: &[u8]) -> Result<Self, DecodeError> {
+               unimplemented!();
+       }
+}
+impl MsgEncodable for UpdateFulfillHTLC {
+       fn encode(&self) -> Vec<u8> {
+               unimplemented!();
+       }
+}
+
+impl MsgDecodable for UpdateFailHTLC {
+       fn decode(_v: &[u8]) -> Result<Self, DecodeError> {
+               unimplemented!();
+       }
+}
+impl MsgEncodable for UpdateFailHTLC {
+       fn encode(&self) -> Vec<u8> {
+               unimplemented!();
+       }
+}
+
+impl MsgDecodable for UpdateFailMalformedHTLC {
+       fn decode(_v: &[u8]) -> Result<Self, DecodeError> {
+               unimplemented!();
+       }
+}
+impl MsgEncodable for UpdateFailMalformedHTLC {
+       fn encode(&self) -> Vec<u8> {
+               unimplemented!();
+       }
+}
+
+impl MsgDecodable for CommitmentSigned {
+       fn decode(_v: &[u8]) -> Result<Self, DecodeError> {
+               unimplemented!();
+       }
+}
+impl MsgEncodable for CommitmentSigned {
+       fn encode(&self) -> Vec<u8> {
+               unimplemented!();
+       }
+}
+
+impl MsgDecodable for RevokeAndACK {
+       fn decode(_v: &[u8]) -> Result<Self, DecodeError> {
+               unimplemented!();
+       }
+}
+impl MsgEncodable for RevokeAndACK {
+       fn encode(&self) -> Vec<u8> {
+               unimplemented!();
+       }
+}
+
+impl MsgDecodable for UpdateFee {
+       fn decode(_v: &[u8]) -> Result<Self, DecodeError> {
+               unimplemented!();
+       }
+}
+impl MsgEncodable for UpdateFee {
+       fn encode(&self) -> Vec<u8> {
+               unimplemented!();
+       }
+}
+
+impl MsgDecodable for ChannelReestablish {
+       fn decode(_v: &[u8]) -> Result<Self, DecodeError> {
+               unimplemented!();
+       }
+}
+impl MsgEncodable for ChannelReestablish {
+       fn encode(&self) -> Vec<u8> {
+               unimplemented!();
+       }
+}
+
+impl MsgDecodable for AnnouncementSignatures {
+       fn decode(_v: &[u8]) -> Result<Self, DecodeError> {
+               unimplemented!();
+       }
+}
+impl MsgEncodable for AnnouncementSignatures {
+       fn encode(&self) -> Vec<u8> {
+               unimplemented!();
+       }
+}
+
+impl MsgDecodable for UnsignedNodeAnnouncement {
+       fn decode(_v: &[u8]) -> Result<Self, DecodeError> {
+               unimplemented!();
+       }
+}
+impl MsgEncodable for UnsignedNodeAnnouncement {
+       fn encode(&self) -> Vec<u8> {
+               let features = self.features.encode();
+               let mut res = Vec::with_capacity(74 + features.len() + self.addresses.len());
+               res.extend_from_slice(&features[..]);
+               res.extend_from_slice(&byte_utils::be32_to_array(self.timestamp));
+               res.extend_from_slice(&self.node_id.serialize());
+               res.extend_from_slice(&self.rgb);
+               res.extend_from_slice(&self.alias);
+               let mut addr_slice = Vec::with_capacity(self.addresses.len() * 18);
+               for addr in self.addresses.iter() {
+                       match addr {
+                               &NetAddress::Dummy => {},
+                               &NetAddress::IPv4{addr, port} => {
+                                       addr_slice.extend_from_slice(&addr);
+                                       addr_slice.extend_from_slice(&byte_utils::be16_to_array(port));
+                               },
+                               &NetAddress::IPv6{addr, port} => {
+                                       addr_slice.extend_from_slice(&addr);
+                                       addr_slice.extend_from_slice(&byte_utils::be16_to_array(port));
+                               },
+                               &NetAddress::OnionV2{addr, port} => {
+                                       addr_slice.extend_from_slice(&addr);
+                                       addr_slice.extend_from_slice(&byte_utils::be16_to_array(port));
+                               },
+                               &NetAddress::OnionV3{ed25519_pubkey, checksum, version} => {
+                                       addr_slice.extend_from_slice(&ed25519_pubkey);
+                                       addr_slice.extend_from_slice(&byte_utils::be16_to_array(checksum));
+                                       addr_slice.push(version);
+                               },
+                       }
+               }
+               res.extend_from_slice(&byte_utils::be16_to_array(addr_slice.len() as u16));
+               res.extend_from_slice(&addr_slice[..]);
+               res
+       }
+}
+
+impl MsgDecodable for NodeAnnouncement {
+       fn decode(_v: &[u8]) -> Result<Self, DecodeError> {
+               unimplemented!();
+       }
+}
+impl MsgEncodable for NodeAnnouncement {
+       fn encode(&self) -> Vec<u8> {
+               unimplemented!();
+       }
+}
+
+impl MsgDecodable for UnsignedChannelAnnouncement {
+       fn decode(_v: &[u8]) -> Result<Self, DecodeError> {
+               unimplemented!();
+       }
+}
+impl MsgEncodable for UnsignedChannelAnnouncement {
+       fn encode(&self) -> Vec<u8> {
+               let features = self.features.encode();
+               let mut res = Vec::with_capacity(172 + features.len());
+               res.extend_from_slice(&features[..]);
+               res.extend_from_slice(&self.chain_hash[..]);
+               res.extend_from_slice(&byte_utils::be64_to_array(self.short_channel_id));
+               res.extend_from_slice(&self.node_id_1.serialize());
+               res.extend_from_slice(&self.node_id_2.serialize());
+               res.extend_from_slice(&self.bitcoin_key_1.serialize());
+               res.extend_from_slice(&self.bitcoin_key_2.serialize());
+               res
+       }
+}
+
+impl MsgDecodable for ChannelAnnouncement {
+       fn decode(_v: &[u8]) -> Result<Self, DecodeError> {
+               unimplemented!();
+       }
+}
+impl MsgEncodable for ChannelAnnouncement {
+       fn encode(&self) -> Vec<u8> {
+               unimplemented!();
+       }
+}
+
+impl MsgDecodable for UnsignedChannelUpdate {
+       fn decode(_v: &[u8]) -> Result<Self, DecodeError> {
+               unimplemented!();
+       }
+}
+impl MsgEncodable for UnsignedChannelUpdate {
+       fn encode(&self) -> Vec<u8> {
+               let mut res = Vec::with_capacity(64);
+               res.extend_from_slice(&self.chain_hash[..]);
+               res.extend_from_slice(&byte_utils::be64_to_array(self.short_channel_id));
+               res.extend_from_slice(&byte_utils::be32_to_array(self.timestamp));
+               res.extend_from_slice(&byte_utils::be16_to_array(self.flags));
+               res.extend_from_slice(&byte_utils::be16_to_array(self.cltv_expiry_delta));
+               res.extend_from_slice(&byte_utils::be64_to_array(self.htlc_minimum_msat));
+               res.extend_from_slice(&byte_utils::be32_to_array(self.fee_base_msat));
+               res.extend_from_slice(&byte_utils::be32_to_array(self.fee_proportional_millionths));
+               res
+       }
+}
+
+impl MsgDecodable for ChannelUpdate {
+       fn decode(_v: &[u8]) -> Result<Self, DecodeError> {
+               unimplemented!();
+       }
+}
+impl MsgEncodable for ChannelUpdate {
+       fn encode(&self) -> Vec<u8> {
+               let mut res = Vec::with_capacity(128);
+               //TODO: Should avoid creating a new secp ctx just for a serialize call :(
+               res.extend_from_slice(&self.signature.serialize_der(&Secp256k1::new())[..]); //TODO: Need in non-der form! (probably elsewhere too)
+               res.extend_from_slice(&self.contents.encode()[..]);
+               res
+       }
+}
+
+impl MsgDecodable for OnionRealm0HopData {
+       fn decode(v: &[u8]) -> Result<Self, DecodeError> {
+               if v.len() != 32 {
+                       return Err(DecodeError::WrongLength);
+               }
+               Ok(OnionRealm0HopData {
+                       short_channel_id: byte_utils::slice_to_be64(&v[0..8]),
+                       amt_to_forward: byte_utils::slice_to_be64(&v[8..16]),
+                       outgoing_cltv_value: byte_utils::slice_to_be32(&v[16..20]),
+               })
+       }
+}
+impl MsgEncodable for OnionRealm0HopData {
+       fn encode(&self) -> Vec<u8> {
+               let mut res = Vec::with_capacity(32);
+               res.extend_from_slice(&byte_utils::be64_to_array(self.short_channel_id));
+               res.extend_from_slice(&byte_utils::be64_to_array(self.amt_to_forward));
+               res.extend_from_slice(&byte_utils::be32_to_array(self.outgoing_cltv_value));
+               res.resize(32, 0);
+               res
+       }
+}
+
+impl MsgDecodable for OnionHopData {
+       fn decode(v: &[u8]) -> Result<Self, DecodeError> {
+               if v.len() != 65 {
+                       return Err(DecodeError::WrongLength);
+               }
+               let realm = v[0];
+               if realm != 0 {
+                       return Err(DecodeError::UnknownRealmByte);
+               }
+               let mut hmac = [0; 32];
+               hmac[..].copy_from_slice(&v[33..65]);
+               Ok(OnionHopData {
+                       realm: realm,
+                       data: try!(OnionRealm0HopData::decode(&v[1..33])),
+                       hmac: hmac,
+               })
+       }
+}
+impl MsgEncodable for OnionHopData {
+       fn encode(&self) -> Vec<u8> {
+               let mut res = Vec::with_capacity(65);
+               res.push(self.realm);
+               res.extend_from_slice(&self.data.encode()[..]);
+               res.extend_from_slice(&self.hmac);
+               res
+       }
+}
+
+impl MsgDecodable for OnionPacket {
+       fn decode(_v: &[u8]) -> Result<Self, DecodeError> {
+               unimplemented!();
+       }
+}
+impl MsgEncodable for OnionPacket {
+       fn encode(&self) -> Vec<u8> {
+               let mut res = Vec::with_capacity(1 + 33 + 20*65 + 32);
+               res.push(self.version);
+               res.extend_from_slice(&self.public_key.serialize());
+               res.extend_from_slice(&self.hop_data);
+               res.extend_from_slice(&self.hmac);
+               res
+       }
+}
+
+impl MsgDecodable for DecodedOnionErrorPacket {
+       fn decode(_v: &[u8]) -> Result<Self, DecodeError> {
+               unimplemented!();
+       }
+}
+impl MsgEncodable for DecodedOnionErrorPacket {
+       fn encode(&self) -> Vec<u8> {
+               let mut res = Vec::with_capacity(32 + 4 + self.failuremsg.len() + self.pad.len());
+               res.extend_from_slice(&self.hmac);
+               res.extend_from_slice(&[((self.failuremsg.len() >> 8) & 0xff) as u8, (self.failuremsg.len() & 0xff) as u8]);
+               res.extend_from_slice(&self.failuremsg);
+               res.extend_from_slice(&[((self.pad.len() >> 8) & 0xff) as u8, (self.pad.len() & 0xff) as u8]);
+               res.extend_from_slice(&self.pad);
+               res
+       }
+}
+
+impl MsgDecodable for OnionErrorPacket {
+       fn decode(_v: &[u8]) -> Result<Self, DecodeError> {
+               unimplemented!();
+       }
+}
+impl MsgEncodable for OnionErrorPacket {
+       fn encode(&self) -> Vec<u8> {
+               unimplemented!();
+       }
+}
+
diff --git a/src/ln/peer_channel_encryptor.rs b/src/ln/peer_channel_encryptor.rs
new file mode 100644 (file)
index 0000000..ceb9ccb
--- /dev/null
@@ -0,0 +1,774 @@
+use ln::msgs::HandleError;
+use ln::msgs;
+
+use secp256k1::Secp256k1;
+use secp256k1::key::{PublicKey,SecretKey};
+use secp256k1::ecdh::SharedSecret;
+
+use rand::{thread_rng,Rng};
+
+use crypto::digest::Digest;
+use crypto::hkdf::{hkdf_extract,hkdf_expand};
+use crypto::sha2::Sha256;
+
+use crypto::aead::{AeadEncryptor, AeadDecryptor};
+
+use util::chacha20poly1305rfc::ChaCha20Poly1305RFC;
+use util::byte_utils;
+
+// Sha256("Noise_XK_secp256k1_ChaChaPoly_SHA256")
+const NOISE_CK: [u8; 32] = [0x26, 0x40, 0xf5, 0x2e, 0xeb, 0xcd, 0x9e, 0x88, 0x29, 0x58, 0x95, 0x1c, 0x79, 0x42, 0x50, 0xee, 0xdb, 0x28, 0x00, 0x2c, 0x05, 0xd7, 0xdc, 0x2e, 0xa0, 0xf1, 0x95, 0x40, 0x60, 0x42, 0xca, 0xf1];
+// Sha256(NOISE_CK || "lightning")
+const NOISE_H: [u8; 32] = [0xd1, 0xfb, 0xf6, 0xde, 0xe4, 0xf6, 0x86, 0xf1, 0x32, 0xfd, 0x70, 0x2c, 0x4a, 0xbf, 0x8f, 0xba, 0x4b, 0xb4, 0x20, 0xd8, 0x9d, 0x2a, 0x04, 0x8a, 0x3c, 0x4f, 0x4c, 0x09, 0x2e, 0x37, 0xb6, 0x76];
+
+pub enum NextNoiseStep {
+       ActOne,
+       ActTwo,
+       ActThree,
+       NoiseComplete,
+}
+
+#[derive(PartialEq)]
+enum NoiseStep {
+       PreActOne,
+       PostActOne,
+       PostActTwo,
+       // When done swap noise_state for NoiseState::Finished
+}
+
+struct BidirectionalNoiseState {
+       h: [u8; 32],
+       ck: [u8; 32],
+}
+enum DirectionalNoiseState {
+       Outbound {
+               ie: SecretKey,
+       },
+       Inbound {
+               ie: Option<PublicKey>, // filled in if state >= PostActOne
+               re: Option<SecretKey>, // filled in if state >= PostActTwo
+               temp_k2: Option<[u8; 32]>, // filled in if state >= PostActTwo
+       }
+}
+enum NoiseState {
+       InProgress {
+               state: NoiseStep,
+               directional_state: DirectionalNoiseState,
+               bidirectional_state: BidirectionalNoiseState,
+       },
+       Finished {
+               sk: [u8; 32],
+               sn: u64,
+               sck: [u8; 32],
+               rk: [u8; 32],
+               rn: u64,
+               rck: [u8; 32],
+       }
+}
+
+pub struct PeerChannelEncryptor {
+       secp_ctx: Secp256k1,
+       their_node_id: Option<PublicKey>, // filled in for outbound, or inbound after noise_state is Finished
+
+       noise_state: NoiseState,
+}
+
+impl PeerChannelEncryptor {
+       pub fn new_outbound(their_node_id: PublicKey) -> PeerChannelEncryptor {
+               let mut rng = thread_rng();
+               let mut key = [0u8; 32];
+               rng.fill_bytes(&mut key);
+
+               let secp_ctx = Secp256k1::new();
+               let sec_key = SecretKey::from_slice(&secp_ctx, &key).unwrap(); //TODO: nicer rng-is-bad error message
+
+               let mut sha = Sha256::new();
+               sha.input(&NOISE_H);
+               sha.input(&their_node_id.serialize()[..]);
+               let mut h = [0; 32];
+               sha.result(&mut h);
+
+               PeerChannelEncryptor {
+                       their_node_id: Some(their_node_id),
+                       secp_ctx: secp_ctx,
+                       noise_state: NoiseState::InProgress {
+                               state: NoiseStep::PreActOne,
+                               directional_state: DirectionalNoiseState::Outbound {
+                                       ie: sec_key,
+                               },
+                               bidirectional_state: BidirectionalNoiseState {
+                                       h: h,
+                                       ck: NOISE_CK,
+                               },
+                       }
+               }
+       }
+
+       pub fn new_inbound(our_node_secret: &SecretKey) -> PeerChannelEncryptor {
+               let secp_ctx = Secp256k1::new();
+
+               let mut sha = Sha256::new();
+               sha.input(&NOISE_H);
+               let our_node_id = PublicKey::from_secret_key(&secp_ctx, our_node_secret).unwrap(); //TODO: nicer bad-node_secret error message
+               sha.input(&our_node_id.serialize()[..]);
+               let mut h = [0; 32];
+               sha.result(&mut h);
+
+               PeerChannelEncryptor {
+                       their_node_id: None,
+                       secp_ctx: secp_ctx,
+                       noise_state: NoiseState::InProgress {
+                               state: NoiseStep::PreActOne,
+                               directional_state: DirectionalNoiseState::Inbound {
+                                       ie: None,
+                                       re: None,
+                                       temp_k2: None,
+                               },
+                               bidirectional_state: BidirectionalNoiseState {
+                                       h: h,
+                                       ck: NOISE_CK,
+                               },
+                       }
+               }
+       }
+
+       #[inline]
+       fn encrypt_with_ad(res: &mut[u8], n: u64, key: &[u8; 32], h: &[u8], plaintext: &[u8]) {
+               let mut nonce = [0; 12];
+               nonce[4..].copy_from_slice(&byte_utils::le64_to_array(n));
+
+               let mut chacha = ChaCha20Poly1305RFC::new(key, &nonce, h);
+               let mut tag = [0; 16];
+               chacha.encrypt(plaintext, &mut res[0..plaintext.len()], &mut tag);
+               res[plaintext.len()..].copy_from_slice(&tag);
+       }
+
+       #[inline]
+       fn decrypt_with_ad(res: &mut[u8], n: u64, key: &[u8; 32], h: &[u8], cyphertext: &[u8]) -> Result<(), HandleError> {
+               let mut nonce = [0; 12];
+               nonce[4..].copy_from_slice(&byte_utils::le64_to_array(n));
+
+               let mut chacha = ChaCha20Poly1305RFC::new(key, &nonce, h);
+               if !chacha.decrypt(&cyphertext[0..cyphertext.len() - 16], res, &cyphertext[cyphertext.len() - 16..]) {
+                       return Err(HandleError{err: "Bad MAC", msg: Some(msgs::ErrorMessage::DisconnectPeer{})});
+               }
+               Ok(())
+       }
+
+       #[inline]
+       fn hkdf(state: &mut BidirectionalNoiseState, ss: SharedSecret) -> [u8; 32] {
+               let sha = Sha256::new();
+               let mut hkdf = [0; 64];
+               {
+                       let mut prk = [0; 32];
+                       hkdf_extract(sha, &state.ck, &ss[..], &mut prk);
+                       hkdf_expand(sha, &prk, &[0;0], &mut hkdf);
+               }
+               state.ck.copy_from_slice(&hkdf[0..32]);
+               let mut res = [0; 32];
+               res.copy_from_slice(&hkdf[32..]);
+               res
+       }
+
+       #[inline]
+       fn outbound_noise_act(secp_ctx: &Secp256k1, state: &mut BidirectionalNoiseState, our_key: &SecretKey, their_key: &PublicKey) -> ([u8; 50], [u8; 32]) {
+               let our_pub = PublicKey::from_secret_key(secp_ctx, &our_key).unwrap(); //TODO: nicer rng-is-bad error message
+
+               let mut sha = Sha256::new();
+               sha.input(&state.h);
+               sha.input(&our_pub.serialize()[..]);
+               sha.result(&mut state.h);
+
+               let ss = SharedSecret::new(secp_ctx, &their_key, &our_key);
+               let temp_k = PeerChannelEncryptor::hkdf(state, ss);
+
+               let mut res = [0; 50];
+               res[1..34].copy_from_slice(&our_pub.serialize()[..]);
+               PeerChannelEncryptor::encrypt_with_ad(&mut res[34..], 0, &temp_k, &state.h, &[0; 0]);
+
+               sha.reset();
+               sha.input(&state.h);
+               sha.input(&res[34..]);
+               sha.result(&mut state.h);
+
+               (res, temp_k)
+       }
+
+       #[inline]
+       fn inbound_noise_act(secp_ctx: &Secp256k1, state: &mut BidirectionalNoiseState, act: &[u8], our_key: &SecretKey) -> Result<(PublicKey, [u8; 32]), HandleError> {
+               assert_eq!(act.len(), 50);
+
+               if act[0] != 0 {
+                       return Err(HandleError{err: "Unknown handshake version number", msg: Some(msgs::ErrorMessage::DisconnectPeer{})});
+               }
+
+               let their_pub = match PublicKey::from_slice(secp_ctx, &act[1..34]) {
+                       Err(_) => return Err(HandleError{err: "Invalid public key", msg: Some(msgs::ErrorMessage::DisconnectPeer{})}),
+                       Ok(key) => key,
+               };
+
+               let mut sha = Sha256::new();
+               sha.input(&state.h);
+               sha.input(&their_pub.serialize()[..]);
+               sha.result(&mut state.h);
+
+               let ss = SharedSecret::new(secp_ctx, &their_pub, &our_key);
+               let temp_k = PeerChannelEncryptor::hkdf(state, ss);
+
+               let mut dec = [0; 0];
+               try!(PeerChannelEncryptor::decrypt_with_ad(&mut dec, 0, &temp_k, &state.h, &act[34..]));
+
+               sha.reset();
+               sha.input(&state.h);
+               sha.input(&act[34..]);
+               sha.result(&mut state.h);
+
+               Ok((their_pub, temp_k))
+       }
+
+       pub fn get_act_one(&mut self) -> [u8; 50] {
+               match self.noise_state {
+                       NoiseState::InProgress { ref mut state, ref directional_state, ref mut bidirectional_state } =>
+                               match directional_state {
+                                       &DirectionalNoiseState::Outbound { ref ie } => {
+                                               if *state != NoiseStep::PreActOne {
+                                                       panic!("Requested act at wrong step");
+                                               }
+
+                                               let (res, _) = PeerChannelEncryptor::outbound_noise_act(&self.secp_ctx, bidirectional_state, &ie, &self.their_node_id.unwrap());
+                                               *state = NoiseStep::PostActOne;
+                                               res
+                                       },
+                                       _ => panic!("Wrong direction for act"),
+                               },
+                       _ => panic!("Cannot get act one after noise handshake completes"),
+               }
+       }
+
+       // Separated for testing:
+       fn process_act_one_with_ephemeral_key(&mut self, act_one: &[u8], our_node_secret: &SecretKey, our_ephemeral: SecretKey) -> Result<[u8; 50], HandleError> {
+               assert_eq!(act_one.len(), 50);
+
+               match self.noise_state {
+                       NoiseState::InProgress { ref mut state, ref mut directional_state, ref mut bidirectional_state } =>
+                               match directional_state {
+                                       &mut DirectionalNoiseState::Inbound { ref mut ie, ref mut re, ref mut temp_k2 } => {
+                                               if *state != NoiseStep::PreActOne {
+                                                       panic!("Requested act at wrong step");
+                                               }
+
+                                               let (their_pub, _) = try!(PeerChannelEncryptor::inbound_noise_act(&self.secp_ctx, bidirectional_state, act_one, &our_node_secret));
+                                               ie.get_or_insert(their_pub);
+
+                                               re.get_or_insert(our_ephemeral);
+
+                                               let (res, temp_k) = PeerChannelEncryptor::outbound_noise_act(&self.secp_ctx, bidirectional_state, &re.unwrap(), &ie.unwrap());
+                                               *temp_k2 = Some(temp_k);
+                                               *state = NoiseStep::PostActTwo;
+                                               Ok(res)
+                                       },
+                                       _ => panic!("Wrong direction for act"),
+                               },
+                       _ => panic!("Cannot get act one after noise handshake completes"),
+               }
+       }
+
+       pub fn process_act_one_with_key(&mut self, act_one: &[u8], our_node_secret: &SecretKey) -> Result<[u8; 50], HandleError> {
+               assert_eq!(act_one.len(), 50);
+
+               let mut rng = thread_rng();
+               let mut key = [0u8; 32];
+               rng.fill_bytes(&mut key);
+               let our_ephemeral_key = SecretKey::from_slice(&self.secp_ctx, &key).unwrap(); //TODO: nicer rng-is-bad error message
+               self.process_act_one_with_ephemeral_key(act_one, our_node_secret, our_ephemeral_key)
+       }
+
+       pub fn process_act_two(&mut self, act_two: &[u8], our_node_secret: &SecretKey) -> Result<[u8; 66], HandleError> {
+               assert_eq!(act_two.len(), 50);
+
+               let mut final_hkdf = [0; 64];
+               let ck;
+               let res: [u8; 66] = match self.noise_state {
+                       NoiseState::InProgress { ref state, ref directional_state, ref mut bidirectional_state } =>
+                               match directional_state {
+                                       &DirectionalNoiseState::Outbound { ref ie } => {
+                                               if *state != NoiseStep::PostActOne {
+                                                       panic!("Requested act at wrong step");
+                                               }
+
+                                               let (re, temp_k2) = try!(PeerChannelEncryptor::inbound_noise_act(&self.secp_ctx, bidirectional_state, act_two, &ie));
+
+                                               let mut res = [0; 66];
+                                               let our_node_id = PublicKey::from_secret_key(&self.secp_ctx, &our_node_secret).unwrap(); //TODO: nicer rng-is-bad error message
+
+                                               PeerChannelEncryptor::encrypt_with_ad(&mut res[1..50], 1, &temp_k2, &bidirectional_state.h, &our_node_id.serialize()[..]);
+
+                                               let mut sha = Sha256::new();
+                                               sha.input(&bidirectional_state.h);
+                                               sha.input(&res[1..50]);
+                                               sha.result(&mut bidirectional_state.h);
+
+                                               let ss = SharedSecret::new(&self.secp_ctx, &re, our_node_secret);
+                                               let temp_k = PeerChannelEncryptor::hkdf(bidirectional_state, ss);
+
+                                               PeerChannelEncryptor::encrypt_with_ad(&mut res[50..], 0, &temp_k, &bidirectional_state.h, &[0; 0]);
+
+                                               sha.reset();
+                                               let mut prk = [0; 32];
+                                               hkdf_extract(sha, &bidirectional_state.ck, &[0; 0], &mut prk);
+                                               hkdf_expand(sha, &prk, &[0;0], &mut final_hkdf);
+                                               ck = bidirectional_state.ck.clone();
+                                               res
+                                       },
+                                       _ => panic!("Wrong direction for act"),
+                               },
+                       _ => panic!("Cannot get act one after noise handshake completes"),
+               };
+
+               let mut sk = [0; 32];
+               let mut rk = [0; 32];
+               sk.copy_from_slice(&final_hkdf[0..32]);
+               rk.copy_from_slice(&final_hkdf[32..]);
+
+               self.noise_state = NoiseState::Finished {
+                       sk: sk,
+                       sn: 0,
+                       sck: ck.clone(),
+                       rk: rk,
+                       rn: 0,
+                       rck: ck,
+               };
+
+               Ok(res)
+       }
+
+       pub fn process_act_three(&mut self, act_three: &[u8]) -> Result<PublicKey, HandleError> {
+               assert_eq!(act_three.len(), 66);
+
+               let mut final_hkdf = [0; 64];
+               let ck;
+               match self.noise_state {
+                       NoiseState::InProgress { ref state, ref directional_state, ref mut bidirectional_state } =>
+                               match directional_state {
+                                       &DirectionalNoiseState::Inbound { ie: _, ref re, ref temp_k2 } => {
+                                               if *state != NoiseStep::PostActTwo {
+                                                       panic!("Requested act at wrong step");
+                                               }
+                                               if act_three[0] != 0 {
+                                                       return Err(HandleError{err: "Unknown handshake version number", msg: Some(msgs::ErrorMessage::DisconnectPeer{})});
+                                               }
+
+                                               let mut their_node_id = [0; 33];
+                                               try!(PeerChannelEncryptor::decrypt_with_ad(&mut their_node_id, 1, &temp_k2.unwrap(), &bidirectional_state.h, &act_three[1..50]));
+                                               self.their_node_id = Some(match PublicKey::from_slice(&self.secp_ctx, &their_node_id) {
+                                                       Ok(key) => key,
+                                                       Err(_) => return Err(HandleError{err: "Bad node_id from peer", msg: Some(msgs::ErrorMessage::DisconnectPeer{})}),
+                                               });
+
+                                               let mut sha = Sha256::new();
+                                               sha.input(&bidirectional_state.h);
+                                               sha.input(&act_three[1..50]);
+                                               sha.result(&mut bidirectional_state.h);
+
+                                               let ss = SharedSecret::new(&self.secp_ctx, &self.their_node_id.unwrap(), &re.unwrap());
+                                               let temp_k = PeerChannelEncryptor::hkdf(bidirectional_state, ss);
+
+                                               try!(PeerChannelEncryptor::decrypt_with_ad(&mut [0; 0], 0, &temp_k, &bidirectional_state.h, &act_three[50..]));
+
+                                               sha.reset();
+                                               let mut prk = [0; 32];
+                                               hkdf_extract(sha, &bidirectional_state.ck, &[0; 0], &mut prk);
+                                               hkdf_expand(sha, &prk, &[0;0], &mut final_hkdf);
+                                               ck = bidirectional_state.ck.clone();
+                                       },
+                                       _ => panic!("Wrong direction for act"),
+                               },
+                       _ => panic!("Cannot get act one after noise handshake completes"),
+               }
+
+               let mut rk = [0; 32];
+               let mut sk = [0; 32];
+               rk.copy_from_slice(&final_hkdf[0..32]);
+               sk.copy_from_slice(&final_hkdf[32..]);
+
+               self.noise_state = NoiseState::Finished {
+                       sk: sk,
+                       sn: 0,
+                       sck: ck.clone(),
+                       rk: rk,
+                       rn: 0,
+                       rck: ck,
+               };
+
+               Ok(self.their_node_id.unwrap().clone())
+       }
+
+       /// Encrypts the given message, returning the encrypted version
+       /// panics if msg.len() > 65535 or Noise handshake has not finished.
+       pub fn encrypt_message(&mut self, msg: &[u8]) -> Vec<u8> {
+               if msg.len() > 65535 {
+                       panic!("Attempted to encrypt message longer than 65535 bytes!");
+               }
+
+               let mut res = Vec::with_capacity(msg.len() + 16*2 + 2);
+               res.resize(msg.len() + 16*2 + 2, 0);
+
+               match self.noise_state {
+                       NoiseState::Finished { ref mut sk, ref mut sn, ref mut sck, rk: _, rn: _, rck: _ } => {
+                               if *sn >= 1000 {
+                                       let mut sha = Sha256::new();
+                                       let mut prk = [0; 32];
+                                       hkdf_extract(sha, sck, sk, &mut prk);
+                                       let mut hkdf = [0; 64];
+                                       hkdf_expand(sha, &prk, &[0;0], &mut hkdf);
+
+                                       sck[..].copy_from_slice(&hkdf[0..32]);
+                                       sk[..].copy_from_slice(&hkdf[32..]);
+                                       *sn = 0;
+                               }
+
+                               Self::encrypt_with_ad(&mut res[0..16+2], *sn, sk, &[0; 0], &byte_utils::be16_to_array(msg.len() as u16));
+                               *sn += 1;
+
+                               Self::encrypt_with_ad(&mut res[16+2..], *sn, sk, &[0; 0], msg);
+                               *sn += 1;
+                       },
+                       _ => panic!("Tried to encrypt a message prior to noise handshake completion"),
+               }
+
+               res
+       }
+
+       /// Decrypts a message length header from the remote peer.
+       /// panics if noise handshake has not yet finished or msg.len() != 18
+       pub fn decrypt_length_header(&mut self, msg: &[u8]) -> Result<u16, HandleError> {
+               assert_eq!(msg.len(), 16+2);
+
+               match self.noise_state {
+                       NoiseState::Finished { sk: _, sn: _, sck: _, ref mut rk, ref mut rn, ref mut rck } => {
+                               if *rn >= 1000 {
+                                       let mut sha = Sha256::new();
+                                       let mut prk = [0; 32];
+                                       hkdf_extract(sha, rck, rk, &mut prk);
+                                       let mut hkdf = [0; 64];
+                                       hkdf_expand(sha, &prk, &[0;0], &mut hkdf);
+
+                                       rck[..].copy_from_slice(&hkdf[0..32]);
+                                       rk[..].copy_from_slice(&hkdf[32..]);
+                                       *rn = 0;
+                               }
+
+                               let mut res = [0; 2];
+                               try!(Self::decrypt_with_ad(&mut res, *rn, rk, &[0; 0], msg));
+                               *rn += 1;
+                               Ok(byte_utils::slice_to_be16(&res))
+                       },
+                       _ => panic!("Tried to encrypt a message prior to noise handshake completion"),
+               }
+       }
+
+       /// Decrypts the given message.
+       /// panics if msg.len() > 65535 + 16
+       pub fn decrypt_message(&mut self, msg: &[u8]) -> Result<Vec<u8>, HandleError> {
+               if msg.len() > 65535 + 16 {
+                       panic!("Attempted to encrypt message longer than 65535 bytes!");
+               }
+
+               match self.noise_state {
+                       NoiseState::Finished { sk: _, sn: _, sck: _, ref rk, ref mut rn, rck: _ } => {
+                               let mut res = Vec::with_capacity(msg.len() - 16);
+                               res.resize(msg.len() - 16, 0);
+                               try!(Self::decrypt_with_ad(&mut res[..], *rn, rk, &[0; 0], msg));
+                               *rn += 1;
+
+                               Ok(res)
+                       },
+                       _ => panic!("Tried to encrypt a message prior to noise handshake completion"),
+               }
+       }
+
+       pub fn get_noise_step(&self) -> NextNoiseStep {
+               match self.noise_state {
+                       NoiseState::InProgress {ref state, ..} => {
+                               match state {
+                                       &NoiseStep::PreActOne => NextNoiseStep::ActOne,
+                                       &NoiseStep::PostActOne => NextNoiseStep::ActTwo,
+                                       &NoiseStep::PostActTwo => NextNoiseStep::ActThree,
+                               }
+                       },
+                       NoiseState::Finished {..} => NextNoiseStep::NoiseComplete,
+               }
+       }
+
+       pub fn is_ready_for_encryption(&self) -> bool {
+               match self.noise_state {
+                       NoiseState::InProgress {..} => { false },
+                       NoiseState::Finished {..} => { true }
+               }
+       }
+}
+
+#[cfg(test)]
+mod tests {
+       use secp256k1::Secp256k1;
+       use secp256k1::key::{PublicKey,SecretKey};
+
+       use bitcoin::util::misc::hex_bytes;
+
+       use ln::peer_channel_encryptor::{PeerChannelEncryptor,NoiseState,DirectionalNoiseState};
+
+       fn get_outbound_peer_for_initiator_test_vectors() -> PeerChannelEncryptor {
+               let secp_ctx = Secp256k1::new();
+               let their_node_id = PublicKey::from_slice(&secp_ctx, &hex_bytes("028d7500dd4c12685d1f568b4c2b5048e8534b873319f3a8daa612b469132ec7f7").unwrap()[..]).unwrap();
+
+               let mut outbound_peer = PeerChannelEncryptor::new_outbound(their_node_id);
+               match outbound_peer.noise_state {
+                       NoiseState::InProgress { state: _, ref mut directional_state, bidirectional_state: _ } => {
+                               *directional_state = DirectionalNoiseState::Outbound { // overwrite ie...
+                                       ie: SecretKey::from_slice(&secp_ctx, &hex_bytes("1212121212121212121212121212121212121212121212121212121212121212").unwrap()[..]).unwrap(),
+                               };
+                       },
+                       _ => panic!()
+               }
+
+               assert_eq!(outbound_peer.get_act_one()[..], hex_bytes("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap()[..]);
+               outbound_peer
+       }
+
+       #[test]
+       fn noise_initiator_test_vectors() {
+               let secp_ctx = Secp256k1::new();
+               let our_node_id = SecretKey::from_slice(&secp_ctx, &hex_bytes("1111111111111111111111111111111111111111111111111111111111111111").unwrap()[..]).unwrap();
+
+               {
+                       // transport-initiator successful handshake
+                       let mut outbound_peer = get_outbound_peer_for_initiator_test_vectors();
+
+                       let act_two = hex_bytes("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap().to_vec();
+                       assert_eq!(outbound_peer.process_act_two(&act_two[..], &our_node_id).unwrap()[..], hex_bytes("00b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba").unwrap()[..]);
+
+                       match outbound_peer.noise_state {
+                               NoiseState::Finished { sk, sn, sck, rk, rn, rck } => {
+                                       assert_eq!(sk, hex_bytes("969ab31b4d288cedf6218839b27a3e2140827047f2c0f01bf5c04435d43511a9").unwrap()[..]);
+                                       assert_eq!(sn, 0);
+                                       assert_eq!(sck, hex_bytes("919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01").unwrap()[..]);
+                                       assert_eq!(rk, hex_bytes("bb9020b8965f4df047e07f955f3c4b88418984aadc5cdb35096b9ea8fa5c3442").unwrap()[..]);
+                                       assert_eq!(rn, 0);
+                                       assert_eq!(rck, hex_bytes("919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01").unwrap()[..]);
+                               },
+                               _ => panic!()
+                       }
+               }
+               {
+                       // transport-initiator act2 short read test
+                       // Can't actually test this cause process_act_two requires you pass the right length!
+               }
+               {
+                       // transport-initiator act2 bad version test
+                       let mut outbound_peer = get_outbound_peer_for_initiator_test_vectors();
+
+                       let act_two = hex_bytes("0102466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap().to_vec();
+                       assert!(outbound_peer.process_act_two(&act_two[..], &our_node_id).is_err());
+               }
+
+               {
+                       // transport-initiator act2 bad key serialization test
+                       let mut outbound_peer = get_outbound_peer_for_initiator_test_vectors();
+
+                       let act_two = hex_bytes("0004466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap().to_vec();
+                       assert!(outbound_peer.process_act_two(&act_two[..], &our_node_id).is_err());
+               }
+
+               {
+                       // transport-initiator act2 bad MAC test
+                       let mut outbound_peer = get_outbound_peer_for_initiator_test_vectors();
+
+                       let act_two = hex_bytes("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730af").unwrap().to_vec();
+                       assert!(outbound_peer.process_act_two(&act_two[..], &our_node_id).is_err());
+               }
+       }
+
+       #[test]
+       fn noise_responder_test_vectors() {
+               let secp_ctx = Secp256k1::new();
+               let our_node_id = SecretKey::from_slice(&secp_ctx, &hex_bytes("2121212121212121212121212121212121212121212121212121212121212121").unwrap()[..]).unwrap();
+               let our_ephemeral = SecretKey::from_slice(&secp_ctx, &hex_bytes("2222222222222222222222222222222222222222222222222222222222222222").unwrap()[..]).unwrap();
+
+               {
+                       // transport-responder successful handshake
+                       let mut inbound_peer = PeerChannelEncryptor::new_inbound(&our_node_id);
+
+                       let act_one = hex_bytes("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap().to_vec();
+                       assert_eq!(inbound_peer.process_act_one_with_ephemeral_key(&act_one[..], &our_node_id, our_ephemeral.clone()).unwrap()[..], hex_bytes("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap()[..]);
+
+                       let act_three = hex_bytes("00b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba").unwrap().to_vec();
+                       // test vector doesn't specify the initiator static key, but its the same as the one
+                       // from trasport-initiator successful handshake
+                       assert_eq!(inbound_peer.process_act_three(&act_three[..]).unwrap().serialize()[..], hex_bytes("034f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa").unwrap()[..]);
+
+                       match inbound_peer.noise_state {
+                               NoiseState::Finished { sk, sn, sck, rk, rn, rck } => {
+                                       assert_eq!(sk, hex_bytes("bb9020b8965f4df047e07f955f3c4b88418984aadc5cdb35096b9ea8fa5c3442").unwrap()[..]);
+                                       assert_eq!(sn, 0);
+                                       assert_eq!(sck, hex_bytes("919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01").unwrap()[..]);
+                                       assert_eq!(rk, hex_bytes("969ab31b4d288cedf6218839b27a3e2140827047f2c0f01bf5c04435d43511a9").unwrap()[..]);
+                                       assert_eq!(rn, 0);
+                                       assert_eq!(rck, hex_bytes("919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01").unwrap()[..]);
+                               },
+                               _ => panic!()
+                       }
+               }
+               {
+                       // transport-responder act1 short read test
+                       // Can't actually test this cause process_act_one requires you pass the right length!
+               }
+               {
+                       // transport-responder act1 bad version test
+                       let mut inbound_peer = PeerChannelEncryptor::new_inbound(&our_node_id);
+
+                       let act_one = hex_bytes("01036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap().to_vec();
+                       assert!(inbound_peer.process_act_one_with_ephemeral_key(&act_one[..], &our_node_id, our_ephemeral.clone()).is_err());
+               }
+               {
+                       // transport-responder act1 bad key serialization test
+                       let mut inbound_peer = PeerChannelEncryptor::new_inbound(&our_node_id);
+
+                       let act_one =hex_bytes("00046360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap().to_vec();
+                       assert!(inbound_peer.process_act_one_with_ephemeral_key(&act_one[..], &our_node_id, our_ephemeral.clone()).is_err());
+               }
+               {
+                       // transport-responder act1 bad MAC test
+                       let mut inbound_peer = PeerChannelEncryptor::new_inbound(&our_node_id);
+
+                       let act_one = hex_bytes("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6b").unwrap().to_vec();
+                       assert!(inbound_peer.process_act_one_with_ephemeral_key(&act_one[..], &our_node_id, our_ephemeral.clone()).is_err());
+               }
+               {
+                       // transport-responder act3 bad version test
+                       let mut inbound_peer = PeerChannelEncryptor::new_inbound(&our_node_id);
+
+                       let act_one = hex_bytes("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap().to_vec();
+                       assert_eq!(inbound_peer.process_act_one_with_ephemeral_key(&act_one[..], &our_node_id, our_ephemeral.clone()).unwrap()[..], hex_bytes("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap()[..]);
+
+                       let act_three = hex_bytes("01b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba").unwrap().to_vec();
+                       assert!(inbound_peer.process_act_three(&act_three[..]).is_err());
+               }
+               {
+                       // transport-responder act3 short read test
+                       // Can't actually test this cause process_act_three requires you pass the right length!
+               }
+               {
+                       // transport-responder act3 bad MAC for ciphertext test
+                       let mut inbound_peer = PeerChannelEncryptor::new_inbound(&our_node_id);
+
+                       let act_one = hex_bytes("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap().to_vec();
+                       assert_eq!(inbound_peer.process_act_one_with_ephemeral_key(&act_one[..], &our_node_id, our_ephemeral.clone()).unwrap()[..], hex_bytes("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap()[..]);
+
+                       let act_three = hex_bytes("00c9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba").unwrap().to_vec();
+                       assert!(inbound_peer.process_act_three(&act_three[..]).is_err());
+               }
+               {
+                       // transport-responder act3 bad rs test
+                       let mut inbound_peer = PeerChannelEncryptor::new_inbound(&our_node_id);
+
+                       let act_one = hex_bytes("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap().to_vec();
+                       assert_eq!(inbound_peer.process_act_one_with_ephemeral_key(&act_one[..], &our_node_id, our_ephemeral.clone()).unwrap()[..], hex_bytes("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap()[..]);
+
+                       let act_three = hex_bytes("00bfe3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa2235536ad09a8ee351870c2bb7f78b754a26c6cef79a98d25139c856d7efd252c2ae73c").unwrap().to_vec();
+                       assert!(inbound_peer.process_act_three(&act_three[..]).is_err());
+               }
+               {
+                       // transport-responder act3 bad MAC test
+                       let mut inbound_peer = PeerChannelEncryptor::new_inbound(&our_node_id);
+
+                       let act_one = hex_bytes("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap().to_vec();
+                       assert_eq!(inbound_peer.process_act_one_with_ephemeral_key(&act_one[..], &our_node_id, our_ephemeral.clone()).unwrap()[..], hex_bytes("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap()[..]);
+
+                       let act_three = hex_bytes("00b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139bb").unwrap().to_vec();
+                       assert!(inbound_peer.process_act_three(&act_three[..]).is_err());
+               }
+       }
+
+
+       #[test]
+       fn message_encryption_decryption_test_vectors() {
+               let secp_ctx = Secp256k1::new();
+
+               // We use the same keys as the initiator and responder test vectors, so we copy those tests
+               // here and use them to encrypt.
+               let mut outbound_peer = get_outbound_peer_for_initiator_test_vectors();
+
+               {
+                       let our_node_id = SecretKey::from_slice(&secp_ctx, &hex_bytes("1111111111111111111111111111111111111111111111111111111111111111").unwrap()[..]).unwrap();
+
+                       let act_two = hex_bytes("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap().to_vec();
+                       assert_eq!(outbound_peer.process_act_two(&act_two[..], &our_node_id).unwrap()[..], hex_bytes("00b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba").unwrap()[..]);
+
+                       match outbound_peer.noise_state {
+                               NoiseState::Finished { sk, sn, sck, rk, rn, rck } => {
+                                       assert_eq!(sk, hex_bytes("969ab31b4d288cedf6218839b27a3e2140827047f2c0f01bf5c04435d43511a9").unwrap()[..]);
+                                       assert_eq!(sn, 0);
+                                       assert_eq!(sck, hex_bytes("919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01").unwrap()[..]);
+                                       assert_eq!(rk, hex_bytes("bb9020b8965f4df047e07f955f3c4b88418984aadc5cdb35096b9ea8fa5c3442").unwrap()[..]);
+                                       assert_eq!(rn, 0);
+                                       assert_eq!(rck, hex_bytes("919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01").unwrap()[..]);
+                               },
+                               _ => panic!()
+                       }
+               }
+
+               let mut inbound_peer;
+
+               {
+                       // transport-responder successful handshake
+                       let our_node_id = SecretKey::from_slice(&secp_ctx, &hex_bytes("2121212121212121212121212121212121212121212121212121212121212121").unwrap()[..]).unwrap();
+                       let our_ephemeral = SecretKey::from_slice(&secp_ctx, &hex_bytes("2222222222222222222222222222222222222222222222222222222222222222").unwrap()[..]).unwrap();
+
+                       inbound_peer = PeerChannelEncryptor::new_inbound(&our_node_id);
+
+                       let act_one = hex_bytes("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap().to_vec();
+                       assert_eq!(inbound_peer.process_act_one_with_ephemeral_key(&act_one[..], &our_node_id, our_ephemeral.clone()).unwrap()[..], hex_bytes("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap()[..]);
+
+                       let act_three = hex_bytes("00b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba").unwrap().to_vec();
+                       // test vector doesn't specify the initiator static key, but its the same as the one
+                       // from trasport-initiator successful handshake
+                       assert_eq!(inbound_peer.process_act_three(&act_three[..]).unwrap().serialize()[..], hex_bytes("034f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa").unwrap()[..]);
+
+                       match inbound_peer.noise_state {
+                               NoiseState::Finished { sk, sn, sck, rk, rn, rck } => {
+                                       assert_eq!(sk, hex_bytes("bb9020b8965f4df047e07f955f3c4b88418984aadc5cdb35096b9ea8fa5c3442").unwrap()[..]);
+                                       assert_eq!(sn, 0);
+                                       assert_eq!(sck, hex_bytes("919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01").unwrap()[..]);
+                                       assert_eq!(rk, hex_bytes("969ab31b4d288cedf6218839b27a3e2140827047f2c0f01bf5c04435d43511a9").unwrap()[..]);
+                                       assert_eq!(rn, 0);
+                                       assert_eq!(rck, hex_bytes("919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01").unwrap()[..]);
+                               },
+                               _ => panic!()
+                       }
+               }
+
+               for i in 0..1005 {
+                       let msg = [0x68, 0x65, 0x6c, 0x6c, 0x6f];
+                       let res = outbound_peer.encrypt_message(&msg);
+                       assert_eq!(res.len(), 5 + 2*16 + 2);
+
+                       let mut len_header = res[0..2+16].to_vec();
+                       assert_eq!(inbound_peer.decrypt_length_header(&len_header[..]).unwrap() as usize, msg.len());
+                       assert_eq!(inbound_peer.decrypt_message(&res[2+16..]).unwrap()[..], msg[..]);
+
+                       if i == 0 {
+                               assert_eq!(res, hex_bytes("cf2b30ddf0cf3f80e7c35a6e6730b59fe802473180f396d88a8fb0db8cbcf25d2f214cf9ea1d95").unwrap());
+                       } else if i == 1 {
+                               assert_eq!(res, hex_bytes("72887022101f0b6753e0c7de21657d35a4cb2a1f5cde2650528bbc8f837d0f0d7ad833b1a256a1").unwrap());
+                       } else if i == 500 {
+                               assert_eq!(res, hex_bytes("178cb9d7387190fa34db9c2d50027d21793c9bc2d40b1e14dcf30ebeeeb220f48364f7a4c68bf8").unwrap());
+                       } else if i == 501 {
+                               assert_eq!(res, hex_bytes("1b186c57d44eb6de4c057c49940d79bb838a145cb528d6e8fd26dbe50a60ca2c104b56b60e45bd").unwrap());
+                       } else if i == 1000 {
+                               assert_eq!(res, hex_bytes("4a2f3cc3b5e78ddb83dcb426d9863d9d9a723b0337c89dd0b005d89f8d3c05c52b76b29b740f09").unwrap());
+                       } else if i == 1001 {
+                               assert_eq!(res, hex_bytes("2ecd8c8a5629d0d02ab457a0fdd0f7b90a192cd46be5ecb6ca570bfc5e268338b1a16cf4ef2d36").unwrap());
+                       }
+               }
+       }
+}
diff --git a/src/ln/peer_handler.rs b/src/ln/peer_handler.rs
new file mode 100644 (file)
index 0000000..1c8701a
--- /dev/null
@@ -0,0 +1,604 @@
+use secp256k1::key::{SecretKey,PublicKey};
+
+use ln::msgs;
+use ln::msgs::{MsgEncodable,MsgDecodable};
+use ln::peer_channel_encryptor::{PeerChannelEncryptor,NextNoiseStep};
+use util::byte_utils;
+use util::events::{EventsProvider,Event};
+
+use std::collections::{HashMap,LinkedList};
+use std::sync::{Arc, Mutex};
+use std::cmp;
+use std::mem;
+use std::hash;
+
+pub struct MessageHandler {
+    pub chan_handler: Arc<msgs::ChannelMessageHandler>,
+    pub route_handler: Arc<msgs::RoutingMessageHandler>,
+}
+
+/// Provides an object which can be used to send data to and which uniquely identifies a connection
+/// to a remote host. You will need to be able to generate multiple of these which meet Eq and
+/// implement Hash to meet the PeerManager API.
+/// For effeciency, Clone should be relatively cheap for this type.
+/// You probably want to just extend an int and put a file descriptor in a struct and implement
+/// send_data.
+pub trait SocketDescriptor : cmp::Eq + hash::Hash + Clone {
+       /// Attempts to send some data from the given Vec starting at the given offset to the peer.
+       /// Returns the amount of data which was sent, possibly 0 if the socket has since disconnected.
+       /// Note that in the disconnected case, a disconnect_event must still fire and further write
+       /// attempts may occur until that time.
+       /// If the returned size is smaller than data.len() - write_offset, a write_available event must
+       /// trigger the next time more data can be written. Additionally, until the a send_data event
+       /// completes fully, no further read_events should trigger on the same peer!
+       /// If a read_event on this descriptor had previously returned true (indicating that read
+       /// events should be paused to prevent DoS in the send buffer), resume_read may be set
+       /// indicating that read events on this descriptor should resume. A resume_read of false does
+       /// *not* imply that further read events should be paused.
+       fn send_data(&mut self, data: &Vec<u8>, write_offset: usize, resume_read: bool) -> usize;
+}
+
+/// Error for PeerManager errors. If you get one of these, you must disconnect the socket and
+/// generate no further read/write_events for the descriptor, only triggering a single
+/// disconnect_event (unless it was provided in response to a new_*_connection event, in which case
+/// no such disconnect_event must be generated and the socket be silently disconencted).
+pub struct PeerHandleError {}
+
+struct Peer {
+       channel_encryptor: PeerChannelEncryptor,
+       their_node_id: Option<PublicKey>,
+
+       pending_outbound_buffer: LinkedList<Vec<u8>>,
+       pending_outbound_buffer_first_msg_offset: usize,
+       awaiting_write_event: bool,
+
+       pending_read_buffer: Vec<u8>,
+       pending_read_buffer_pos: usize,
+       pending_read_is_header: bool,
+}
+
+struct PeerHolder<Descriptor: SocketDescriptor> {
+       peers: HashMap<Descriptor, Peer>,
+       /// Only add to this set when noise completes:
+       node_id_to_descriptor: HashMap<PublicKey, Descriptor>,
+}
+
+pub struct PeerManager<Descriptor: SocketDescriptor> {
+       message_handler: MessageHandler,
+       peers: Mutex<PeerHolder<Descriptor>>,
+       pending_events: Mutex<Vec<Event>>,
+       our_node_secret: SecretKey,
+}
+
+
+macro_rules! encode_msg {
+       ($msg: expr, $msg_code: expr) => {
+               {
+                       let just_msg = $msg.encode();
+                       let mut encoded_msg = Vec::with_capacity(just_msg.len() + 2);
+                       encoded_msg.extend_from_slice(&byte_utils::be16_to_array($msg_code));
+                       encoded_msg.extend_from_slice(&just_msg[..]);
+                       encoded_msg
+               }
+       }
+}
+
+/// Manages and reacts to connection events. You probably want to use file descriptors as PeerIds.
+/// PeerIds may repeat, but only after disconnect_event() has been called.
+impl<Descriptor: SocketDescriptor> PeerManager<Descriptor> {
+       pub fn new(message_handler: MessageHandler, our_node_secret: SecretKey) -> PeerManager<Descriptor> {
+               PeerManager {
+                       message_handler: message_handler,
+                       peers: Mutex::new(PeerHolder { peers: HashMap::new(), node_id_to_descriptor: HashMap::new() }),
+                       pending_events: Mutex::new(Vec::new()),
+                       our_node_secret: our_node_secret,
+               }
+       }
+
+       /// Indicates a new outbound connection has been established to a node with the given node_id.
+       /// Note that if an Err is returned here you MUST NOT call disconnect_event for the new
+       /// descriptor but must disconnect the connection immediately.
+       /// Returns some bytes to send to the remote node.
+       /// Panics if descriptor is duplicative with some other descriptor which has not yet has a
+       /// disconnect_event.
+       pub fn new_outbound_connection(&self, their_node_id: PublicKey, descriptor: Descriptor) -> Result<Vec<u8>, PeerHandleError> {
+               let mut peer_encryptor = PeerChannelEncryptor::new_outbound(their_node_id.clone());
+               let res = peer_encryptor.get_act_one().to_vec();
+               let pending_read_buffer = [0; 50].to_vec(); // Noise act two is 50 bytes
+
+               let mut peers = self.peers.lock().unwrap();
+               if peers.peers.insert(descriptor, Peer {
+                       channel_encryptor: peer_encryptor,
+                       their_node_id: Some(their_node_id),
+
+                       pending_outbound_buffer: LinkedList::new(),
+                       pending_outbound_buffer_first_msg_offset: 0,
+                       awaiting_write_event: false,
+
+                       pending_read_buffer: pending_read_buffer,
+                       pending_read_buffer_pos: 0,
+                       pending_read_is_header: false,
+               }).is_some() {
+                       panic!("PeerManager driver duplicated descriptors!");
+               };
+               Ok(res)
+       }
+
+       /// Indicates a new inbound connection has been established.
+       /// May refuse the connection by returning an Err, but will never write bytes to the remote end
+       /// (outbound connector always speaks first). Note that if an Err is returned here you MUST NOT
+       /// call disconnect_event for the new descriptor but must disconnect the connection
+       /// immediately.
+       /// Panics if descriptor is duplicative with some other descriptor which has not yet has a
+       /// disconnect_event.
+       pub fn new_inbound_connection(&self, descriptor: Descriptor) -> Result<(), PeerHandleError> {
+               let peer_encryptor = PeerChannelEncryptor::new_inbound(&self.our_node_secret);
+               let pending_read_buffer = [0; 50].to_vec(); // Noise act one is 50 bytes
+
+               let mut peers = self.peers.lock().unwrap();
+               if peers.peers.insert(descriptor, Peer {
+                       channel_encryptor: peer_encryptor,
+                       their_node_id: None,
+
+                       pending_outbound_buffer: LinkedList::new(),
+                       pending_outbound_buffer_first_msg_offset: 0,
+                       awaiting_write_event: false,
+
+                       pending_read_buffer: pending_read_buffer,
+                       pending_read_buffer_pos: 0,
+                       pending_read_is_header: false,
+               }).is_some() {
+                       panic!("PeerManager driver duplicated descriptors!");
+               };
+               Ok(())
+       }
+
+       fn do_attempt_write_data(descriptor: &mut Descriptor, peer: &mut Peer) {
+               while !peer.awaiting_write_event {
+                       if {
+                               let next_buff = match peer.pending_outbound_buffer.front() {
+                                       None => return,
+                                       Some(buff) => buff,
+                               };
+                               let should_be_reading = peer.pending_outbound_buffer.len() < 10;
+
+                               let data_sent = descriptor.send_data(next_buff, peer.pending_outbound_buffer_first_msg_offset, should_be_reading);
+                               peer.pending_outbound_buffer_first_msg_offset += data_sent;
+                               if peer.pending_outbound_buffer_first_msg_offset == next_buff.len() { true } else { false }
+                       } {
+                               peer.pending_outbound_buffer_first_msg_offset = 0;
+                               peer.pending_outbound_buffer.pop_front();
+                       } else {
+                               peer.awaiting_write_event = true;
+                       }
+               }
+       }
+
+       /// Indicates that there is room to write data to the given socket descriptor.
+       /// May return an Err to indicate that the connection should be closed.
+       /// Will most likely call send_data on the descriptor passed in (or the descriptor handed into
+       /// new_*_connection) before returning. Thus, be very careful with reentrancy issues! The
+       /// invariants around calling write_event in case a write did not fully complete must still
+       /// hold - be ready to call write_event again if a write call generated here isn't sufficient!
+       /// Panics if the descriptor was not previously registered in a new_*_connection event.
+       pub fn write_event(&self, descriptor: &mut Descriptor) -> Result<(), PeerHandleError> {
+               let mut peers = self.peers.lock().unwrap();
+               match peers.peers.get_mut(descriptor) {
+                       None => panic!("Descriptor for write_event is not already known to PeerManager"),
+                       Some(peer) => {
+                               peer.awaiting_write_event = false;
+                               Self::do_attempt_write_data(descriptor, peer);
+                       }
+               };
+               Ok(())
+       }
+
+       /// Indicates that data was read from the given socket descriptor.
+       /// May return an Err to indicate that the connection should be closed.
+       /// Will very likely call send_data on the descriptor passed in (or a descriptor handed into
+       /// new_*_connection) before returning. Thus, be very careful with reentrancy issues! The
+       /// invariants around calling write_event in case a write did not fully complete must still
+       /// hold. Note that this function will often call send_data on many peers before returning, not
+       /// just this peer!
+       /// If Ok(true) is returned, further read_events should not be triggered until a write_event on
+       /// this file descriptor has resume_read set (preventing DoS issues in the send buffer). Note
+       /// that this must be true even if a send_data call with resume_read=true was made during the
+       /// course of this function!
+       /// Panics if the descriptor was not previously registered in a new_*_connection event.
+       pub fn read_event(&self, peer_descriptor: &mut Descriptor, data: Vec<u8>) -> Result<bool, PeerHandleError> {
+               let mut upstream_events = Vec::new();
+               let pause_read = {
+                       let mut peers = self.peers.lock().unwrap();
+                       let (should_insert_node_id, pause_read) = match peers.peers.get_mut(peer_descriptor) {
+                               None => panic!("Descriptor for read_event is not already known to PeerManager"),
+                               Some(peer) => {
+                                       assert!(peer.pending_read_buffer.len() > 0);
+                                       assert!(peer.pending_read_buffer.len() > peer.pending_read_buffer_pos);
+
+                                       macro_rules! try_potential_handleerror {
+                                               ($thing: expr) => {
+                                                       match $thing {
+                                                               Ok(x) => x,
+                                                               Err(_e) => {
+                                                                       //TODO: Handle e appropriately!
+                                                                       return Err(PeerHandleError{});
+                                                               }
+                                                       };
+                                               }
+                                       }
+
+                                       macro_rules! try_potential_decodeerror {
+                                               ($thing: expr) => {
+                                                       match $thing {
+                                                               Ok(x) => x,
+                                                               Err(_e) => {
+                                                                       //TODO: Handle e?
+                                                                       return Err(PeerHandleError{});
+                                                               }
+                                                       };
+                                               }
+                                       }
+
+                                       macro_rules! encode_and_send_msg {
+                                               ($msg: expr, $msg_code: expr) => {
+                                                       peer.pending_outbound_buffer.push_back(peer.channel_encryptor.encrypt_message(&encode_msg!($msg, $msg_code)[..]));
+                                               }
+                                       }
+
+                                       let mut insert_node_id = None;
+
+                                       let mut read_pos = 0;
+                                       while read_pos < data.len() {
+                                               {
+                                                       let data_to_copy = cmp::min(peer.pending_read_buffer.len() - peer.pending_read_buffer_pos, data.len() - read_pos);
+                                                       peer.pending_read_buffer[peer.pending_read_buffer_pos..peer.pending_read_buffer_pos + data_to_copy].copy_from_slice(&data[read_pos..read_pos + data_to_copy]);
+                                                       read_pos += data_to_copy;
+                                                       peer.pending_read_buffer_pos += data_to_copy;
+                                               }
+                                               if peer.pending_read_buffer_pos == peer.pending_read_buffer.len() {
+                                                       let next_step = peer.channel_encryptor.get_noise_step();
+                                                       match next_step {
+                                                               NextNoiseStep::ActOne => {
+                                                                       let act_two = try_potential_handleerror!(peer.channel_encryptor.process_act_one_with_key(&peer.pending_read_buffer[..], &self.our_node_secret)).to_vec();
+                                                                       peer.pending_outbound_buffer.push_back(act_two);
+                                                                       peer.pending_read_buffer = [0; 66].to_vec(); // act three is 66 bytes long
+                                                               },
+                                                               NextNoiseStep::ActTwo => {
+                                                                       let act_three = try_potential_handleerror!(peer.channel_encryptor.process_act_two(&peer.pending_read_buffer[..], &self.our_node_secret)).to_vec();
+                                                                       peer.pending_outbound_buffer.push_back(act_three);
+                                                                       peer.pending_read_buffer = [0; 18].to_vec(); // Message length header is 18 bytes
+
+                                                                       insert_node_id = Some(peer.their_node_id.unwrap());
+                                                                       encode_and_send_msg!(msgs::Init {
+                                                                               global_features: msgs::GlobalFeatures::new(),
+                                                                               local_features: msgs::LocalFeatures::new(),
+                                                                       }, 16);
+                                                               },
+                                                               NextNoiseStep::ActThree => {
+                                                                       let their_node_id = try_potential_handleerror!(peer.channel_encryptor.process_act_three(&peer.pending_read_buffer[..]));
+                                                                       peer.pending_read_buffer = [0; 18].to_vec(); // Message length header is 18 bytes
+                                                                       peer.pending_read_is_header = true;
+                                                                       peer.their_node_id = Some(their_node_id);
+                                                                       insert_node_id = Some(peer.their_node_id.unwrap());
+                                                               },
+                                                               NextNoiseStep::NoiseComplete => {
+                                                                       if peer.pending_read_is_header {
+                                                                               let msg_len = try_potential_handleerror!(peer.channel_encryptor.decrypt_length_header(&peer.pending_read_buffer[..]));
+                                                                               peer.pending_read_buffer = Vec::with_capacity(msg_len as usize + 16);
+                                                                               peer.pending_read_buffer.resize(msg_len as usize + 16, 0);
+                                                                               if msg_len < 2 + 16 { // Need at least the message type tag
+                                                                                       return Err(PeerHandleError{});
+                                                                               }
+                                                                               peer.pending_read_is_header = false;
+                                                                       } else {
+                                                                               let msg_data = try_potential_handleerror!(peer.channel_encryptor.decrypt_message(&peer.pending_read_buffer[..]));
+                                                                               assert!(msg_data.len() >= 2);
+
+                                                                               let msg_type = byte_utils::slice_to_be16(&msg_data[0..2]);
+                                                                               match msg_type {
+                                                                                       // Connection control:
+                                                                                       16 => {
+                                                                                               let msg = try_potential_decodeerror!(msgs::Init::decode(&msg_data[2..]));
+                                                                                               if msg.global_features.requires_unknown_bits() {
+                                                                                                       return Err(PeerHandleError{});
+                                                                                               }
+                                                                                               if msg.local_features.requires_unknown_bits() {
+                                                                                                       return Err(PeerHandleError{});
+                                                                                               }
+                                                                                               //TODO: Store features!
+                                                                                       },
+                                                                                       17 => {
+                                                                                               // Error msg
+                                                                                       },
+                                                                                       18 => { }, // ping
+                                                                                       19 => { }, // pong
+
+                                                                                       // Channel control:
+                                                                                       32 => {
+                                                                                               let msg = try_potential_decodeerror!(msgs::OpenChannel::decode(&msg_data[2..]));
+                                                                                               let resp = try_potential_handleerror!(self.message_handler.chan_handler.handle_open_channel(&peer.their_node_id.unwrap(), &msg));
+                                                                                               encode_and_send_msg!(resp, 33);
+                                                                                       },
+                                                                                       33 => {
+                                                                                               let msg = try_potential_decodeerror!(msgs::AcceptChannel::decode(&msg_data[2..]));
+                                                                                               try_potential_handleerror!(self.message_handler.chan_handler.handle_accept_channel(&peer.their_node_id.unwrap(), &msg));
+                                                                                       },
+
+                                                                                       34 => {
+                                                                                               let msg = try_potential_decodeerror!(msgs::FundingCreated::decode(&msg_data[2..]));
+                                                                                               let resp = try_potential_handleerror!(self.message_handler.chan_handler.handle_funding_created(&peer.their_node_id.unwrap(), &msg));
+                                                                                               encode_and_send_msg!(resp, 35);
+                                                                                       },
+                                                                                       35 => {
+                                                                                               let msg = try_potential_decodeerror!(msgs::FundingSigned::decode(&msg_data[2..]));
+                                                                                               try_potential_handleerror!(self.message_handler.chan_handler.handle_funding_signed(&peer.their_node_id.unwrap(), &msg));
+                                                                                       },
+                                                                                       36 => {
+                                                                                               let msg = try_potential_decodeerror!(msgs::FundingLocked::decode(&msg_data[2..]));
+                                                                                               let resp_option = try_potential_handleerror!(self.message_handler.chan_handler.handle_funding_locked(&peer.their_node_id.unwrap(), &msg));
+                                                                                               match resp_option {
+                                                                                                       Some(resp) => encode_and_send_msg!(resp, 259),
+                                                                                                       None => {},
+                                                                                               }
+                                                                                       },
+
+                                                                                       38 => {
+                                                                                               let msg = try_potential_decodeerror!(msgs::Shutdown::decode(&msg_data[2..]));
+                                                                                               try_potential_handleerror!(self.message_handler.chan_handler.handle_shutdown(&peer.their_node_id.unwrap(), &msg));
+                                                                                       },
+                                                                                       39 => {
+                                                                                               let msg = try_potential_decodeerror!(msgs::ClosingSigned::decode(&msg_data[2..]));
+                                                                                               try_potential_handleerror!(self.message_handler.chan_handler.handle_closing_signed(&peer.their_node_id.unwrap(), &msg));
+                                                                                       },
+
+                                                                                       128 => {
+                                                                                               let msg = try_potential_decodeerror!(msgs::UpdateAddHTLC::decode(&msg_data[2..]));
+                                                                                               try_potential_handleerror!(self.message_handler.chan_handler.handle_update_add_htlc(&peer.their_node_id.unwrap(), &msg));
+                                                                                       },
+                                                                                       130 => {
+                                                                                               let msg = try_potential_decodeerror!(msgs::UpdateFulfillHTLC::decode(&msg_data[2..]));
+                                                                                               let resp_option = try_potential_handleerror!(self.message_handler.chan_handler.handle_update_fulfill_htlc(&peer.their_node_id.unwrap(), &msg));
+                                                                                               match resp_option {
+                                                                                                       Some(resps) => {
+                                                                                                               for resp in resps.0 {
+                                                                                                                       encode_and_send_msg!(resp, 128);
+                                                                                                               }
+                                                                                                               encode_and_send_msg!(resps.1, 132);
+                                                                                                       },
+                                                                                                       None => {},
+                                                                                               }
+                                                                                       },
+                                                                                       131 => {
+                                                                                               let msg = try_potential_decodeerror!(msgs::UpdateFailHTLC::decode(&msg_data[2..]));
+                                                                                               let resp_option = try_potential_handleerror!(self.message_handler.chan_handler.handle_update_fail_htlc(&peer.their_node_id.unwrap(), &msg));
+                                                                                               match resp_option {
+                                                                                                       Some(resps) => {
+                                                                                                               for resp in resps.0 {
+                                                                                                                       encode_and_send_msg!(resp, 128);
+                                                                                                               }
+                                                                                                               encode_and_send_msg!(resps.1, 132);
+                                                                                                       },
+                                                                                                       None => {},
+                                                                                               }
+                                                                                       },
+                                                                                       135 => {
+                                                                                               let msg = try_potential_decodeerror!(msgs::UpdateFailMalformedHTLC::decode(&msg_data[2..]));
+                                                                                               let resp_option = try_potential_handleerror!(self.message_handler.chan_handler.handle_update_fail_malformed_htlc(&peer.their_node_id.unwrap(), &msg));
+                                                                                               match resp_option {
+                                                                                                       Some(resps) => {
+                                                                                                               for resp in resps.0 {
+                                                                                                                       encode_and_send_msg!(resp, 128);
+                                                                                                               }
+                                                                                                               encode_and_send_msg!(resps.1, 132);
+                                                                                                       },
+                                                                                                       None => {},
+                                                                                               }
+                                                                                       },
+
+                                                                                       132 => {
+                                                                                               let msg = try_potential_decodeerror!(msgs::CommitmentSigned::decode(&msg_data[2..]));
+                                                                                               let resp = try_potential_handleerror!(self.message_handler.chan_handler.handle_commitment_signed(&peer.their_node_id.unwrap(), &msg));
+                                                                                               encode_and_send_msg!(resp, 133);
+                                                                                       },
+                                                                                       133 => {
+                                                                                               let msg = try_potential_decodeerror!(msgs::RevokeAndACK::decode(&msg_data[2..]));
+                                                                                               try_potential_handleerror!(self.message_handler.chan_handler.handle_revoke_and_ack(&peer.their_node_id.unwrap(), &msg));
+                                                                                       },
+
+                                                                                       134 => {
+                                                                                               let msg = try_potential_decodeerror!(msgs::UpdateFee::decode(&msg_data[2..]));
+                                                                                               try_potential_handleerror!(self.message_handler.chan_handler.handle_update_fee(&peer.their_node_id.unwrap(), &msg));
+                                                                                       },
+                                                                                       136 => { }, // TODO: channel_reestablish
+
+                                                                                       // Routing control:
+                                                                                       259 => {
+                                                                                               let msg = try_potential_decodeerror!(msgs::AnnouncementSignatures::decode(&msg_data[2..]));
+                                                                                               try_potential_handleerror!(self.message_handler.chan_handler.handle_announcement_signatures(&peer.their_node_id.unwrap(), &msg));
+                                                                                       },
+                                                                                       256 => {
+                                                                                               let msg = try_potential_decodeerror!(msgs::ChannelAnnouncement::decode(&msg_data[2..]));
+                                                                                               let should_forward = try_potential_handleerror!(self.message_handler.route_handler.handle_channel_announcement(&msg));
+
+                                                                                               if should_forward {
+                                                                                                       // TODO: forward msg along to all our other peers!
+                                                                                               }
+                                                                                       },
+                                                                                       257 => {
+                                                                                               let msg = try_potential_decodeerror!(msgs::NodeAnnouncement::decode(&msg_data[2..]));
+                                                                                               try_potential_handleerror!(self.message_handler.route_handler.handle_node_announcement(&msg));
+                                                                                       },
+                                                                                       258 => {
+                                                                                               let msg = try_potential_decodeerror!(msgs::ChannelUpdate::decode(&msg_data[2..]));
+                                                                                               try_potential_handleerror!(self.message_handler.route_handler.handle_channel_update(&msg));
+                                                                                       },
+                                                                                       _ => {
+                                                                                               if (msg_type & 1) == 0 {
+                                                                                                       //TODO: Fail all channels. Kill the peer!
+                                                                                                       return Err(PeerHandleError{});
+                                                                                               }
+                                                                                       },
+                                                                               }
+
+                                                                               peer.pending_read_buffer = [0; 18].to_vec();
+                                                                               peer.pending_read_is_header = true;
+                                                                       }
+                                                               }
+                                                       }
+                                                       peer.pending_read_buffer_pos = 0;
+                                               }
+                                       }
+
+                                       Self::do_attempt_write_data(peer_descriptor, peer);
+
+                                       (insert_node_id /* should_insert_node_id */, peer.pending_outbound_buffer.len() > 10) // pause_read
+                               }
+                       };
+
+                       match should_insert_node_id {
+                               Some(node_id) => { peers.node_id_to_descriptor.insert(node_id, peer_descriptor.clone()); },
+                               None => {}
+                       };
+
+                       // TODO: There are some DoS attacks here where you can flood someone's outbound send
+                       // buffer by doing things like announcing channels on another node. We should be willing to
+                       // drop optional-ish messages when send buffers get full!
+
+                       let mut events_generated = self.message_handler.chan_handler.get_and_clear_pending_events();
+                       for event in events_generated.drain(..) {
+                               macro_rules! get_peer_for_forwarding {
+                                       ($node_id: expr, $handle_no_such_peer: block) => {
+                                               {
+                                                       let descriptor = match peers.node_id_to_descriptor.get($node_id) {
+                                                               Some(descriptor) => descriptor.clone(),
+                                                               None => {
+                                                                       $handle_no_such_peer;
+                                                                       continue;
+                                                               },
+                                                       };
+                                                       match peers.peers.get_mut(&descriptor) {
+                                                               Some(peer) => {
+                                                                       (descriptor, peer)
+                                                               },
+                                                               None => panic!("Inconsistent peers set state!"),
+                                                       }
+                                               }
+                                       }
+                               }
+                               match event {
+                                       Event::FundingGenerationReady {..} => { /* Hand upstream */ },
+                                       Event::FundingBroadcastSafe {..} => { /* Hand upstream */ },
+                                       Event::PaymentReceived {..} => { /* Hand upstream */ },
+
+                                       Event::PendingHTLCsForwardable {..} => {
+                                               //TODO: Handle upstream in some confused form so that upstream just knows
+                                               //to call us somehow?
+                                       },
+                                       Event::SendFundingCreated { ref node_id, ref msg } => {
+                                               let (mut descriptor, peer) = get_peer_for_forwarding!(node_id, {
+                                                               //TODO: generate a DiscardFunding event indicating to the wallet that
+                                                               //they should just throw away this funding transaction
+                                                       });
+                                               peer.pending_outbound_buffer.push_back(peer.channel_encryptor.encrypt_message(&encode_msg!(msg, 34)));
+                                               Self::do_attempt_write_data(&mut descriptor, peer);
+                                               continue;
+                                       },
+                                       Event::SendFundingLocked { ref node_id, ref msg, ref announcement_sigs } => {
+                                               let (mut descriptor, peer) = get_peer_for_forwarding!(node_id, {
+                                                               //TODO: Do whatever we're gonna do for handling dropped messages
+                                                       });
+                                               peer.pending_outbound_buffer.push_back(peer.channel_encryptor.encrypt_message(&encode_msg!(msg, 36)));
+                                               match announcement_sigs {
+                                                       &Some(ref announce_msg) => peer.pending_outbound_buffer.push_back(peer.channel_encryptor.encrypt_message(&encode_msg!(announce_msg, 259))),
+                                                       &None => {},
+                                               }
+                                               Self::do_attempt_write_data(&mut descriptor, peer);
+                                               continue;
+                                       },
+                                       Event::SendHTLCs { ref node_id, ref msgs, ref commitment_msg } => {
+                                               let (mut descriptor, peer) = get_peer_for_forwarding!(node_id, {
+                                                               //TODO: Do whatever we're gonna do for handling dropped messages
+                                                       });
+                                               for msg in msgs {
+                                                       peer.pending_outbound_buffer.push_back(peer.channel_encryptor.encrypt_message(&encode_msg!(msg, 128)));
+                                               }
+                                               peer.pending_outbound_buffer.push_back(peer.channel_encryptor.encrypt_message(&encode_msg!(commitment_msg, 132)));
+                                               Self::do_attempt_write_data(&mut descriptor, peer);
+                                               continue;
+                                       },
+                                       Event::SendFulfillHTLC { ref node_id, ref msg } => {
+                                               let (mut descriptor, peer) = get_peer_for_forwarding!(node_id, {
+                                                               //TODO: Do whatever we're gonna do for handling dropped messages
+                                                       });
+                                               peer.pending_outbound_buffer.push_back(peer.channel_encryptor.encrypt_message(&encode_msg!(msg, 130)));
+                                               Self::do_attempt_write_data(&mut descriptor, peer);
+                                               continue;
+                                       },
+                                       Event::BroadcastChannelAnnouncement { ref msg, ref update_msg } => {
+                                               let encoded_msg = encode_msg!(msg, 256);
+                                               let encoded_update_msg = encode_msg!(update_msg, 258);
+
+                                               for (ref descriptor, ref mut peer) in peers.peers.iter_mut() {
+                                                       if !peer.channel_encryptor.is_ready_for_encryption() {
+                                                               continue
+                                                       }
+                                                       match peer.their_node_id {
+                                                               None => continue,
+                                                               Some(their_node_id) => {
+                                                                       if their_node_id == msg.contents.node_id_1 || their_node_id == msg.contents.node_id_2 {
+                                                                               continue
+                                                                       }
+                                                               }
+                                                       }
+                                                       peer.pending_outbound_buffer.push_back(peer.channel_encryptor.encrypt_message(&encoded_msg[..]));
+                                                       peer.pending_outbound_buffer.push_back(peer.channel_encryptor.encrypt_message(&encoded_update_msg[..]));
+                                                       Self::do_attempt_write_data(&mut (*descriptor).clone(), peer);
+                                               }
+                                               continue;
+                                       },
+                               }
+
+                               upstream_events.push(event);
+                       }
+
+                       pause_read
+               };
+
+               let mut pending_events = self.pending_events.lock().unwrap();
+               for event in upstream_events.drain(..) {
+                       pending_events.push(event);
+               }
+
+               Ok(pause_read)
+       }
+
+       /// Indicates that the given socket descriptor's connection is now closed.
+       /// This must be called even if a PeerHandleError was given for a read_event or write_event,
+       /// but must NOT be called if a PeerHandleError was provided out of a new_*_connection event!
+       /// Panics if the descriptor was not previously registered in a successful new_*_connection event.
+       pub fn disconnect_event(&self, descriptor: &Descriptor) {
+               let mut peers = self.peers.lock().unwrap();
+               let peer_option = peers.peers.remove(descriptor);
+               match peer_option {
+                       None => panic!("Descriptor for disconnect_event is not already known to PeerManager"),
+                       Some(peer) => {
+                               match peer.their_node_id {
+                                       Some(node_id) => { peers.node_id_to_descriptor.remove(&node_id); },
+                                       None => {}
+                               }
+                               //TODO: Notify the chan_handler that this node disconnected, and do something about
+                               //handling response messages that were queued for sending (maybe the send buffer
+                               //needs to be unencrypted?)
+                       }
+               };
+       }
+}
+
+impl<Descriptor: SocketDescriptor> EventsProvider for PeerManager<Descriptor> {
+       fn get_and_clear_pending_events(&self) -> Vec<Event> {
+               let mut pending_events = self.pending_events.lock().unwrap();
+               let mut ret = Vec::new();
+               mem::swap(&mut ret, &mut *pending_events);
+               ret
+       }
+}
diff --git a/src/ln/router.rs b/src/ln/router.rs
new file mode 100644 (file)
index 0000000..2419106
--- /dev/null
@@ -0,0 +1,921 @@
+use secp256k1::key::PublicKey;
+use secp256k1::{Secp256k1,Message};
+
+use bitcoin::util::hash::Sha256dHash;
+
+use ln::msgs::{HandleError,RoutingMessageHandler,MsgEncodable,NetAddress,GlobalFeatures};
+use ln::msgs;
+
+use std::cmp;
+use std::sync::RwLock;
+use std::collections::{HashMap,BinaryHeap};
+use std::collections::hash_map::Entry;
+
+/// A hop in a route
+pub struct RouteHop {
+       pub pubkey: PublicKey,
+       /// The channel that should be used from the previous hop to reach this node.
+       pub short_channel_id: u64,
+       /// The fee taken on this hop. For the last hop, this should be the full value of the payment.
+       pub fee_msat: u64,
+       /// The CLTV delta added for this hop. For the last hop, this should be the full CLTV value
+       /// expected at the destination, NOT a delta.
+       pub cltv_expiry_delta: u32,
+}
+
+/// A route from us through the network to a destination
+pub struct Route {
+       /// The list of hops, NOT INCLUDING our own, where the last hop is the destination. Thus, this
+       /// must always be at least length one. By protocol rules, this may not currently exceed 20 in
+       /// length.
+       pub hops: Vec<RouteHop>,
+}
+
+struct DirectionalChannelInfo {
+       src_node_id: PublicKey,
+       last_update: u32,
+       enabled: bool,
+       cltv_expiry_delta: u16,
+       htlc_minimum_msat: u64,
+       fee_base_msat: u32,
+       fee_proportional_millionths: u32,
+}
+
+struct ChannelInfo {
+       features: GlobalFeatures,
+       one_to_two: DirectionalChannelInfo,
+       two_to_one: DirectionalChannelInfo,
+}
+
+struct NodeInfo {
+       #[cfg(feature = "non_bitcoin_chain_hash_routing")]
+    channels: Vec<(u64, Sha256dHash)>,
+       #[cfg(not(feature = "non_bitcoin_chain_hash_routing"))]
+    channels: Vec<u64>,
+
+       lowest_inbound_channel_fee_base_msat: u32,
+       lowest_inbound_channel_fee_proportional_millionths: u32,
+
+       features: GlobalFeatures,
+       last_update: u32,
+       rgb: [u8; 3],
+       alias: [u8; 32],
+       addresses: Vec<NetAddress>,
+}
+
+struct NetworkMap {
+       #[cfg(feature = "non_bitcoin_chain_hash_routing")]
+       channels: HashMap<(u64, Sha256dHash), ChannelInfo>,
+       #[cfg(not(feature = "non_bitcoin_chain_hash_routing"))]
+       channels: HashMap<u64, ChannelInfo>,
+
+       our_node_id: PublicKey,
+       nodes: HashMap<PublicKey, NodeInfo>,
+}
+
+impl NetworkMap {
+       #[cfg(feature = "non_bitcoin_chain_hash_routing")]
+       #[inline]
+       fn get_key(short_channel_id: u64, chain_hash: Sha256dHash) -> (u64, Sha256dHash) {
+               (short_channel_id, chain_hash)
+       }
+
+       #[cfg(not(feature = "non_bitcoin_chain_hash_routing"))]
+       #[inline]
+       fn get_key(short_channel_id: u64, _: Sha256dHash) -> u64 {
+               short_channel_id
+       }
+}
+
+/// A channel descriptor which provides a last-hop route to get_route
+pub struct RouteHint {
+       pub src_node_id: PublicKey,
+       pub short_channel_id: u64,
+       pub fee_base_msat: u64,
+       pub fee_proportional_millionths: u32,
+       pub cltv_expiry_delta: u16,
+       pub htlc_minimum_msat: u64,
+}
+
+/// Tracks a view of the network, receiving updates from peers and generating Routes to
+/// payment destinations.
+pub struct Router {
+       secp_ctx: Secp256k1,
+       network_map: RwLock<NetworkMap>,
+}
+
+macro_rules! secp_verify_sig {
+       ( $secp_ctx: expr, $msg: expr, $sig: expr, $pubkey: expr ) => {
+               match $secp_ctx.verify($msg, $sig, $pubkey) {
+                       Ok(_) => {},
+                       Err(_) => return Err(HandleError{err: "Invalid signature from remote node", msg: None}),
+               }
+       };
+}
+
+impl RoutingMessageHandler for Router {
+       fn handle_node_announcement(&self, msg: &msgs::NodeAnnouncement) -> Result<(), HandleError> {
+               let msg_hash = Message::from_slice(&Sha256dHash::from_data(&msg.contents.encode()[..])[..]).unwrap();
+               secp_verify_sig!(self.secp_ctx, &msg_hash, &msg.signature, &msg.contents.node_id);
+
+               let mut network = self.network_map.write().unwrap();
+               match network.nodes.get_mut(&msg.contents.node_id) {
+                       None => Err(HandleError{err: "No existing channels for node_announcement", msg: None}),
+                       Some(node) => {
+                               if node.last_update >= msg.contents.timestamp {
+                                       return Err(HandleError{err: "Update older than last processed update", msg: None});
+                               }
+
+                               node.features = msg.contents.features.clone();
+                               node.last_update = msg.contents.timestamp;
+                               node.rgb = msg.contents.rgb;
+                               node.alias = msg.contents.alias;
+                               node.addresses = msg.contents.addresses.clone();
+                               Ok(())
+                       }
+               }
+       }
+
+       fn handle_channel_announcement(&self, msg: &msgs::ChannelAnnouncement) -> Result<bool, HandleError> {
+               let msg_hash = Message::from_slice(&Sha256dHash::from_data(&msg.contents.encode()[..])[..]).unwrap();
+               secp_verify_sig!(self.secp_ctx, &msg_hash, &msg.node_signature_1, &msg.contents.node_id_1);
+               secp_verify_sig!(self.secp_ctx, &msg_hash, &msg.node_signature_2, &msg.contents.node_id_2);
+               secp_verify_sig!(self.secp_ctx, &msg_hash, &msg.bitcoin_signature_1, &msg.contents.bitcoin_key_1);
+               secp_verify_sig!(self.secp_ctx, &msg_hash, &msg.bitcoin_signature_2, &msg.contents.bitcoin_key_2);
+
+               //TODO: Call blockchain thing to ask if the short_channel_id is valid
+               //TODO: Only allow bitcoin chain_hash
+
+               if msg.contents.features.requires_unknown_bits() {
+                       return Err(HandleError{err: "Channel announcement required unknown feature flags", msg: None});
+               }
+
+               let mut network = self.network_map.write().unwrap();
+
+               match network.channels.entry(NetworkMap::get_key(msg.contents.short_channel_id, msg.contents.chain_hash)) {
+                       Entry::Occupied(_) => {
+                               //TODO: because asking the blockchain if short_channel_id is valid is only optional
+                               //in the blockchain API, we need to handle it smartly here, though its unclear
+                               //exactly how...
+                               return Err(HandleError{err: "Already have knowledge of channel", msg: None})
+                       },
+                       Entry::Vacant(entry) => {
+                               entry.insert(ChannelInfo {
+                                       features: msg.contents.features.clone(),
+                                       one_to_two: DirectionalChannelInfo {
+                                               src_node_id: msg.contents.node_id_1.clone(),
+                                               last_update: 0,
+                                               enabled: false,
+                                               cltv_expiry_delta: u16::max_value(),
+                                               htlc_minimum_msat: u64::max_value(),
+                                               fee_base_msat: u32::max_value(),
+                                               fee_proportional_millionths: u32::max_value(),
+                                       },
+                                       two_to_one: DirectionalChannelInfo {
+                                               src_node_id: msg.contents.node_id_2.clone(),
+                                               last_update: 0,
+                                               enabled: false,
+                                               cltv_expiry_delta: u16::max_value(),
+                                               htlc_minimum_msat: u64::max_value(),
+                                               fee_base_msat: u32::max_value(),
+                                               fee_proportional_millionths: u32::max_value(),
+                                       }
+                               });
+                       }
+               };
+
+               macro_rules! add_channel_to_node {
+                       ( $node_id: expr ) => {
+                               match network.nodes.entry($node_id) {
+                                       Entry::Occupied(node_entry) => {
+                                               node_entry.into_mut().channels.push(NetworkMap::get_key(msg.contents.short_channel_id, msg.contents.chain_hash));
+                                       },
+                                       Entry::Vacant(node_entry) => {
+                                               node_entry.insert(NodeInfo {
+                                                       channels: vec!(NetworkMap::get_key(msg.contents.short_channel_id, msg.contents.chain_hash)),
+                                                       lowest_inbound_channel_fee_base_msat: u32::max_value(),
+                                                       lowest_inbound_channel_fee_proportional_millionths: u32::max_value(),
+                                                       features: GlobalFeatures::new(),
+                                                       last_update: 0,
+                                                       rgb: [0; 3],
+                                                       alias: [0; 32],
+                                                       addresses: Vec::new(),
+                                               });
+                                       }
+                               }
+                       };
+               }
+
+               add_channel_to_node!(msg.contents.node_id_1);
+               add_channel_to_node!(msg.contents.node_id_2);
+
+               Ok(!msg.contents.features.supports_unknown_bits())
+       }
+
+       fn handle_channel_update(&self, msg: &msgs::ChannelUpdate) -> Result<(), HandleError> {
+               let mut network = self.network_map.write().unwrap();
+               let dest_node_id;
+               let chan_enabled = msg.contents.flags & (1 << 1) != (1 << 1);
+               let chan_was_enabled;
+
+               match network.channels.get_mut(&NetworkMap::get_key(msg.contents.short_channel_id, msg.contents.chain_hash)) {
+                       None => return Err(HandleError{err: "Couldn't find channel for update", msg: None}),
+                       Some(channel) => {
+                               macro_rules! maybe_update_channel_info {
+                                       ( $target: expr) => {
+                                               if $target.last_update >= msg.contents.timestamp {
+                                                       return Err(HandleError{err: "Update older than last processed update", msg: None});
+                                               }
+                                               chan_was_enabled = $target.enabled;
+                                               $target.last_update = msg.contents.timestamp;
+                                               $target.enabled = chan_enabled;
+                                               $target.cltv_expiry_delta = msg.contents.cltv_expiry_delta;
+                                               $target.htlc_minimum_msat = msg.contents.htlc_minimum_msat;
+                                               $target.fee_base_msat = msg.contents.fee_base_msat;
+                                               $target.fee_proportional_millionths = msg.contents.fee_proportional_millionths;
+                                       }
+                               }
+
+                               let msg_hash = Message::from_slice(&Sha256dHash::from_data(&msg.contents.encode()[..])[..]).unwrap();
+                               if msg.contents.flags & 1 == 1 {
+                                       dest_node_id = channel.one_to_two.src_node_id.clone();
+                                       secp_verify_sig!(self.secp_ctx, &msg_hash, &msg.signature, &channel.two_to_one.src_node_id);
+                                       maybe_update_channel_info!(channel.two_to_one);
+                               } else {
+                                       dest_node_id = channel.two_to_one.src_node_id.clone();
+                                       secp_verify_sig!(self.secp_ctx, &msg_hash, &msg.signature, &channel.one_to_two.src_node_id);
+                                       maybe_update_channel_info!(channel.one_to_two);
+                               }
+                       }
+               }
+
+               if chan_enabled {
+                       let node = network.nodes.get_mut(&dest_node_id).unwrap();
+                       node.lowest_inbound_channel_fee_base_msat = cmp::min(node.lowest_inbound_channel_fee_base_msat, msg.contents.fee_base_msat);
+                       node.lowest_inbound_channel_fee_proportional_millionths = cmp::min(node.lowest_inbound_channel_fee_proportional_millionths, msg.contents.fee_proportional_millionths);
+               } else if chan_was_enabled {
+                       let mut lowest_inbound_channel_fee_base_msat = u32::max_value();
+                       let mut lowest_inbound_channel_fee_proportional_millionths = u32::max_value();
+
+                       {
+                               let node = network.nodes.get(&dest_node_id).unwrap();
+
+                               for chan_id in node.channels.iter() {
+                                       let chan = network.channels.get(chan_id).unwrap();
+                                       if chan.one_to_two.src_node_id == dest_node_id {
+                                               lowest_inbound_channel_fee_base_msat = cmp::min(lowest_inbound_channel_fee_base_msat, chan.two_to_one.fee_base_msat);
+                                               lowest_inbound_channel_fee_proportional_millionths = cmp::min(lowest_inbound_channel_fee_proportional_millionths, chan.two_to_one.fee_proportional_millionths);
+                                       } else {
+                                               lowest_inbound_channel_fee_base_msat = cmp::min(lowest_inbound_channel_fee_base_msat, chan.one_to_two.fee_base_msat);
+                                               lowest_inbound_channel_fee_proportional_millionths = cmp::min(lowest_inbound_channel_fee_proportional_millionths, chan.one_to_two.fee_proportional_millionths);
+                                       }
+                               }
+                       }
+
+                       //TODO: satisfy the borrow-checker without a double-map-lookup :(
+                       let mut_node = network.nodes.get_mut(&dest_node_id).unwrap();
+                       mut_node.lowest_inbound_channel_fee_base_msat = lowest_inbound_channel_fee_base_msat;
+                       mut_node.lowest_inbound_channel_fee_proportional_millionths = lowest_inbound_channel_fee_proportional_millionths;
+               }
+
+               Ok(())
+       }
+}
+
+#[derive(Eq, PartialEq)]
+struct RouteGraphNode {
+       pubkey: PublicKey,
+       lowest_fee_to_peer_through_node: u64,
+}
+
+impl cmp::Ord for RouteGraphNode {
+       fn cmp(&self, other: &RouteGraphNode) -> cmp::Ordering {
+               other.lowest_fee_to_peer_through_node.cmp(&self.lowest_fee_to_peer_through_node)
+                       .then_with(|| other.pubkey.serialize().cmp(&self.pubkey.serialize()))
+       }
+}
+
+impl cmp::PartialOrd for RouteGraphNode {
+       fn partial_cmp(&self, other: &RouteGraphNode) -> Option<cmp::Ordering> {
+               Some(self.cmp(other))
+       }
+}
+
+impl Router {
+       pub fn new(our_pubkey: PublicKey) -> Router {
+               let mut nodes = HashMap::new();
+               nodes.insert(our_pubkey.clone(), NodeInfo {
+                       channels: Vec::new(),
+                       lowest_inbound_channel_fee_base_msat: u32::max_value(),
+                       lowest_inbound_channel_fee_proportional_millionths: u32::max_value(),
+                       features: GlobalFeatures::new(),
+                       last_update: 0,
+                       rgb: [0; 3],
+                       alias: [0; 32],
+                       addresses: Vec::new(),
+               });
+               Router {
+                       secp_ctx: Secp256k1::new(),
+                       network_map: RwLock::new(NetworkMap {
+                               channels: HashMap::new(),
+                               our_node_id: our_pubkey,
+                               nodes: nodes,
+                       }),
+               }
+       }
+
+       /// Marks a node as having failed a route. This will avoid re-using the node in routes for now,
+       /// with an expotnential decay in node "badness". Note that there is deliberately no
+       /// mark_channel_bad as a node may simply lie and suggest that an upstream channel from it is
+       /// what failed the route and not the node itself. Instead, setting the blamed_upstream_node
+       /// boolean will reduce the penalty, returning the node to usability faster. If the node is
+       /// behaving correctly, it will disable the failing channel and we will use it again next time.
+       pub fn mark_node_bad(&self, _node_id: &PublicKey, _blamed_upstream_node: bool) {
+               unimplemented!();
+       }
+
+       /// Gets a route from us to the given target node.
+       /// Extra routing hops between known nodes and the target will be used if they are included in
+       /// last_hops.
+       /// The fees on channels from us to next-hops are ignored (as they are assumed to all be
+       /// equal), however the enabled/disabled bit on such channels as well as the htlc_minimum_msat
+       /// *is* checked as they may change based on the receiving node.
+       pub fn get_route(&self, target: &PublicKey, last_hops: &Vec<RouteHint>, final_value_msat: u64, final_cltv: u32) -> Result<Route, HandleError> {
+               // TODO: Obviously *only* using total fee cost sucks. We should consider weighting by
+               // uptime/success in using a node in the past.
+               let network = self.network_map.read().unwrap();
+
+               if *target == network.our_node_id {
+                       return Err(HandleError{err: "Cannot generate a route to ourselves", msg: None});
+               }
+
+               // We do a dest-to-source Dijkstra's sorting by each node's distance from the destination
+               // plus the minimum per-HTLC fee to get from it to another node (aka "shitty A*").
+               // TODO: There are a few tweaks we could do, including possibly pre-calculating more stuff
+               // to use as the A* heuristic beyond just the cost to get one node further than the current
+               // one.
+
+               let mut targets = BinaryHeap::new(); //TODO: Do we care about switching to eg Fibbonaci heap?
+               let mut dist = HashMap::with_capacity(network.nodes.len());
+               for (key, node) in network.nodes.iter() {
+                       dist.insert(key.clone(), (u64::max_value(),
+                               node.lowest_inbound_channel_fee_base_msat as u64,
+                               node.lowest_inbound_channel_fee_proportional_millionths as u64,
+                               RouteHop {
+                                       pubkey: PublicKey::new(),
+                                       short_channel_id: 0,
+                                       fee_msat: 0,
+                                       cltv_expiry_delta: 0,
+                       }));
+               }
+
+               macro_rules! add_entry {
+                       // Adds entry which goes from the node pointed to by $directional_info to
+                       // $dest_node_id over the channel with id $chan_id with fees described in
+                       // $directional_info.
+                       ( $chan_id: expr, $dest_node_id: expr, $directional_info: expr, $starting_fee_msat: expr ) => {
+                               //TODO: Explore simply adding fee to hit htlc_minimum_msat
+                               if $starting_fee_msat as u64 + final_value_msat > $directional_info.htlc_minimum_msat {
+                                       let new_fee = $directional_info.fee_base_msat as u64 + ($starting_fee_msat + final_value_msat) * ($directional_info.fee_proportional_millionths as u64) / 1000000;
+                                       let mut total_fee = $starting_fee_msat as u64;
+                                       let old_entry = dist.get_mut(&$directional_info.src_node_id).unwrap();
+                                       if $directional_info.src_node_id != network.our_node_id {
+                                               // Ignore new_fee for channel-from-us as we assume all channels-from-us
+                                               // will have the same effective-fee
+                                               total_fee += new_fee;
+                                               total_fee += old_entry.2 * (final_value_msat + total_fee) / 1000000 + old_entry.1;
+                                       }
+                                       let new_graph_node = RouteGraphNode {
+                                               pubkey: $directional_info.src_node_id,
+                                               lowest_fee_to_peer_through_node: total_fee,
+                                       };
+                                       if old_entry.0 > total_fee {
+                                               targets.push(new_graph_node);
+                                               old_entry.0 = total_fee;
+                                               old_entry.3 = RouteHop {
+                                                       pubkey: $dest_node_id.clone(),
+                                                       short_channel_id: $chan_id.clone(),
+                                                       fee_msat: new_fee, // This field is ignored on the last-hop anyway
+                                                       cltv_expiry_delta: $directional_info.cltv_expiry_delta as u32,
+                                               }
+                                       }
+                               }
+                       };
+               }
+
+               macro_rules! add_entries_to_cheapest_to_target_node {
+                       ( $node: expr, $node_id: expr, $fee_to_target_msat: expr ) => {
+                               for chan_id in $node.channels.iter() {
+                                       let chan = network.channels.get(chan_id).unwrap();
+                                       if chan.one_to_two.src_node_id == *$node_id {
+                                               // ie $node is one, ie next hop in A* is two, via the two_to_one channel
+                                               if chan.two_to_one.enabled {
+                                                       add_entry!(chan_id, chan.one_to_two.src_node_id, chan.two_to_one, $fee_to_target_msat);
+                                               }
+                                       } else {
+                                               if chan.one_to_two.enabled {
+                                                       add_entry!(chan_id, chan.two_to_one.src_node_id, chan.one_to_two, $fee_to_target_msat);
+                                               }
+                                       }
+                               }
+                       };
+               }
+
+               match network.nodes.get(target) {
+                       None => {},
+                       Some(node) => {
+                               add_entries_to_cheapest_to_target_node!(node, target, 0);
+                       },
+               }
+
+               for hop in last_hops.iter() {
+                       if network.nodes.get(&hop.src_node_id).is_some() {
+                               add_entry!(hop.short_channel_id, target, hop, 0);
+                       }
+               }
+
+               while let Some(RouteGraphNode { pubkey, lowest_fee_to_peer_through_node }) = targets.pop() {
+                       if pubkey == network.our_node_id {
+                               let mut res = vec!(dist.remove(&network.our_node_id).unwrap().3);
+                               while res.last().unwrap().pubkey != *target {
+                                       let new_entry = dist.remove(&res.last().unwrap().pubkey).unwrap().3;
+                                       res.last_mut().unwrap().fee_msat = new_entry.fee_msat;
+                                       res.last_mut().unwrap().cltv_expiry_delta = new_entry.cltv_expiry_delta;
+                                       res.push(new_entry);
+                               }
+                               res.last_mut().unwrap().fee_msat = final_value_msat;
+                               res.last_mut().unwrap().cltv_expiry_delta = final_cltv;
+                               return Ok(Route {
+                                       hops: res
+                               });
+                       }
+
+                       match network.nodes.get(&pubkey) {
+                               None => {},
+                               Some(node) => {
+                                       let mut fee = lowest_fee_to_peer_through_node - node.lowest_inbound_channel_fee_base_msat as u64;
+                                       fee -= node.lowest_inbound_channel_fee_proportional_millionths as u64 * (fee + final_value_msat) / 1000000;
+                                       add_entries_to_cheapest_to_target_node!(node, &pubkey, fee);
+                               },
+                       }
+               }
+
+               Err(HandleError{err: "Failed to find a path to the given destination", msg: None})
+       }
+}
+
+#[cfg(test)]
+mod tests {
+       use ln::router::{Router,NodeInfo,NetworkMap,ChannelInfo,DirectionalChannelInfo,RouteHint};
+       use ln::msgs::GlobalFeatures;
+
+       use bitcoin::util::misc::hex_bytes;
+       use bitcoin::util::hash::Sha256dHash;
+
+       use secp256k1::key::{PublicKey,SecretKey};
+       use secp256k1::Secp256k1;
+
+       #[test]
+       fn route_test() {
+               let secp_ctx = Secp256k1::new();
+               let our_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex_bytes("0101010101010101010101010101010101010101010101010101010101010101").unwrap()[..]).unwrap()).unwrap();
+               let router = Router::new(our_id);
+
+               // Build network from our_id to node8:
+               //
+               //        -1(1)2- node1 -1(3)2-
+               //       /                     \
+               // our_id                       - node3
+               //       \                     /
+               //        -1(2)2- node2 -1(4)2-
+               //
+               //
+               // chan1 1-to-2: disabled
+               // chan1 2-to-1: enabled, 0 fee
+               //
+               // chan2 1-to-2: enabled, ignored fee
+               // chan2 2-to-1: enabled, 0 fee
+               //
+               // chan3 1-to-2: enabled, 0 fee
+               // chan3 2-to-1: enabled, 100 msat fee
+               //
+               // chan4 1-to-2: enabled, 100% fee
+               // chan4 2-to-1: enabled, 0 fee
+               //
+               //
+               //
+               //       -1(5)2- node4 -1(8)2--
+               //       |         2          |
+               //       |       (11)         |
+               //      /          1           \
+               // node3--1(6)2- node5 -1(9)2--- node7 (not in global route map)
+               //      \                      /
+               //       -1(7)2- node6 -1(10)2-
+               //
+               // chan5  1-to-2: enabled, 100 msat fee
+               // chan5  2-to-1: enabled, 0 fee
+               //
+               // chan6  1-to-2: enabled, 0 fee
+               // chan6  2-to-1: enabled, 0 fee
+               //
+               // chan7  1-to-2: enabled, 100% fee
+               // chan7  2-to-1: enabled, 0 fee
+               //
+               // chan8  1-to-2: enabled, variable fee (0 then 1000 msat)
+               // chan8  2-to-1: enabled, 0 fee
+               //
+               // chan9  1-to-2: enabled, 1001 msat fee
+               // chan9  2-to-1: enabled, 0 fee
+               //
+               // chan10 1-to-2: enabled, 0 fee
+               // chan10 2-to-1: enabled, 0 fee
+               //
+               // chan11 1-to-2: enabled, 0 fee
+               // chan11 2-to-1: enabled, 0 fee
+
+               let node1 = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex_bytes("0202020202020202020202020202020202020202020202020202020202020202").unwrap()[..]).unwrap()).unwrap();
+               let node2 = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex_bytes("0303030303030303030303030303030303030303030303030303030303030303").unwrap()[..]).unwrap()).unwrap();
+               let node3 = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex_bytes("0404040404040404040404040404040404040404040404040404040404040404").unwrap()[..]).unwrap()).unwrap();
+               let node4 = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex_bytes("0505050505050505050505050505050505050505050505050505050505050505").unwrap()[..]).unwrap()).unwrap();
+               let node5 = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex_bytes("0606060606060606060606060606060606060606060606060606060606060606").unwrap()[..]).unwrap()).unwrap();
+               let node6 = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex_bytes("0707070707070707070707070707070707070707070707070707070707070707").unwrap()[..]).unwrap()).unwrap();
+               let node7 = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex_bytes("0808080808080808080808080808080808080808080808080808080808080808").unwrap()[..]).unwrap()).unwrap();
+
+               let zero_hash = Sha256dHash::from_data(&[0; 32]);
+
+               {
+                       let mut network = router.network_map.write().unwrap();
+
+                       network.nodes.insert(node1.clone(), NodeInfo {
+                               channels: vec!(NetworkMap::get_key(1, zero_hash.clone()), NetworkMap::get_key(3, zero_hash.clone())),
+                               lowest_inbound_channel_fee_base_msat: 100,
+                               lowest_inbound_channel_fee_proportional_millionths: 0,
+                               features: GlobalFeatures::new(),
+                               last_update: 1,
+                               rgb: [0; 3],
+                               alias: [0; 32],
+                               addresses: Vec::new(),
+                       });
+                       network.channels.insert(NetworkMap::get_key(1, zero_hash.clone()), ChannelInfo {
+                               features: GlobalFeatures::new(),
+                               one_to_two: DirectionalChannelInfo {
+                                       src_node_id: our_id.clone(),
+                                       last_update: 0,
+                                       enabled: false,
+                                       cltv_expiry_delta: u16::max_value(), // This value should be ignored
+                                       htlc_minimum_msat: 0,
+                                       fee_base_msat: u32::max_value(), // This value should be ignored
+                                       fee_proportional_millionths: u32::max_value(), // This value should be ignored
+                               }, two_to_one: DirectionalChannelInfo {
+                                       src_node_id: node1.clone(),
+                                       last_update: 0,
+                                       enabled: true,
+                                       cltv_expiry_delta: 0,
+                                       htlc_minimum_msat: 0,
+                                       fee_base_msat: 0,
+                                       fee_proportional_millionths: 0,
+                               },
+                       });
+                       network.nodes.insert(node2.clone(), NodeInfo {
+                               channels: vec!(NetworkMap::get_key(2, zero_hash.clone()), NetworkMap::get_key(4, zero_hash.clone())),
+                               lowest_inbound_channel_fee_base_msat: 0,
+                               lowest_inbound_channel_fee_proportional_millionths: 0,
+                               features: GlobalFeatures::new(),
+                               last_update: 1,
+                               rgb: [0; 3],
+                               alias: [0; 32],
+                               addresses: Vec::new(),
+                       });
+                       network.channels.insert(NetworkMap::get_key(2, zero_hash.clone()), ChannelInfo {
+                               features: GlobalFeatures::new(),
+                               one_to_two: DirectionalChannelInfo {
+                                       src_node_id: our_id.clone(),
+                                       last_update: 0,
+                                       enabled: true,
+                                       cltv_expiry_delta: u16::max_value(), // This value should be ignored
+                                       htlc_minimum_msat: 0,
+                                       fee_base_msat: u32::max_value(), // This value should be ignored
+                                       fee_proportional_millionths: u32::max_value(), // This value should be ignored
+                               }, two_to_one: DirectionalChannelInfo {
+                                       src_node_id: node2.clone(),
+                                       last_update: 0,
+                                       enabled: true,
+                                       cltv_expiry_delta: 0,
+                                       htlc_minimum_msat: 0,
+                                       fee_base_msat: 0,
+                                       fee_proportional_millionths: 0,
+                               },
+                       });
+                       network.nodes.insert(node3.clone(), NodeInfo {
+                               channels: vec!(
+                                       NetworkMap::get_key(3, zero_hash.clone()),
+                                       NetworkMap::get_key(4, zero_hash.clone()),
+                                       NetworkMap::get_key(5, zero_hash.clone()),
+                                       NetworkMap::get_key(6, zero_hash.clone()),
+                                       NetworkMap::get_key(7, zero_hash.clone())),
+                               lowest_inbound_channel_fee_base_msat: 0,
+                               lowest_inbound_channel_fee_proportional_millionths: 0,
+                               features: GlobalFeatures::new(),
+                               last_update: 1,
+                               rgb: [0; 3],
+                               alias: [0; 32],
+                               addresses: Vec::new(),
+                       });
+                       network.channels.insert(NetworkMap::get_key(3, zero_hash.clone()), ChannelInfo {
+                               features: GlobalFeatures::new(),
+                               one_to_two: DirectionalChannelInfo {
+                                       src_node_id: node1.clone(),
+                                       last_update: 0,
+                                       enabled: true,
+                                       cltv_expiry_delta: (3 << 8) | 1,
+                                       htlc_minimum_msat: 0,
+                                       fee_base_msat: 0,
+                                       fee_proportional_millionths: 0,
+                               }, two_to_one: DirectionalChannelInfo {
+                                       src_node_id: node3.clone(),
+                                       last_update: 0,
+                                       enabled: true,
+                                       cltv_expiry_delta: (3 << 8) | 2,
+                                       htlc_minimum_msat: 0,
+                                       fee_base_msat: 100,
+                                       fee_proportional_millionths: 0,
+                               },
+                       });
+                       network.channels.insert(NetworkMap::get_key(4, zero_hash.clone()), ChannelInfo {
+                               features: GlobalFeatures::new(),
+                               one_to_two: DirectionalChannelInfo {
+                                       src_node_id: node2.clone(),
+                                       last_update: 0,
+                                       enabled: true,
+                                       cltv_expiry_delta: (4 << 8) | 1,
+                                       htlc_minimum_msat: 0,
+                                       fee_base_msat: 0,
+                                       fee_proportional_millionths: 1000000,
+                               }, two_to_one: DirectionalChannelInfo {
+                                       src_node_id: node3.clone(),
+                                       last_update: 0,
+                                       enabled: true,
+                                       cltv_expiry_delta: (4 << 8) | 2,
+                                       htlc_minimum_msat: 0,
+                                       fee_base_msat: 0,
+                                       fee_proportional_millionths: 0,
+                               },
+                       });
+                       network.nodes.insert(node4.clone(), NodeInfo {
+                               channels: vec!(NetworkMap::get_key(5, zero_hash.clone()), NetworkMap::get_key(11, zero_hash.clone())),
+                               lowest_inbound_channel_fee_base_msat: 0,
+                               lowest_inbound_channel_fee_proportional_millionths: 0,
+                               features: GlobalFeatures::new(),
+                               last_update: 1,
+                               rgb: [0; 3],
+                               alias: [0; 32],
+                               addresses: Vec::new(),
+                       });
+                       network.channels.insert(NetworkMap::get_key(5, zero_hash.clone()), ChannelInfo {
+                               features: GlobalFeatures::new(),
+                               one_to_two: DirectionalChannelInfo {
+                                       src_node_id: node3.clone(),
+                                       last_update: 0,
+                                       enabled: true,
+                                       cltv_expiry_delta: (5 << 8) | 1,
+                                       htlc_minimum_msat: 0,
+                                       fee_base_msat: 100,
+                                       fee_proportional_millionths: 0,
+                               }, two_to_one: DirectionalChannelInfo {
+                                       src_node_id: node4.clone(),
+                                       last_update: 0,
+                                       enabled: true,
+                                       cltv_expiry_delta: (5 << 8) | 2,
+                                       htlc_minimum_msat: 0,
+                                       fee_base_msat: 0,
+                                       fee_proportional_millionths: 0,
+                               },
+                       });
+                       network.nodes.insert(node5.clone(), NodeInfo {
+                               channels: vec!(NetworkMap::get_key(6, zero_hash.clone()), NetworkMap::get_key(11, zero_hash.clone())),
+                               lowest_inbound_channel_fee_base_msat: 0,
+                               lowest_inbound_channel_fee_proportional_millionths: 0,
+                               features: GlobalFeatures::new(),
+                               last_update: 1,
+                               rgb: [0; 3],
+                               alias: [0; 32],
+                               addresses: Vec::new(),
+                       });
+                       network.channels.insert(NetworkMap::get_key(6, zero_hash.clone()), ChannelInfo {
+                               features: GlobalFeatures::new(),
+                               one_to_two: DirectionalChannelInfo {
+                                       src_node_id: node3.clone(),
+                                       last_update: 0,
+                                       enabled: true,
+                                       cltv_expiry_delta: (6 << 8) | 1,
+                                       htlc_minimum_msat: 0,
+                                       fee_base_msat: 0,
+                                       fee_proportional_millionths: 0,
+                               }, two_to_one: DirectionalChannelInfo {
+                                       src_node_id: node5.clone(),
+                                       last_update: 0,
+                                       enabled: true,
+                                       cltv_expiry_delta: (6 << 8) | 2,
+                                       htlc_minimum_msat: 0,
+                                       fee_base_msat: 0,
+                                       fee_proportional_millionths: 0,
+                               },
+                       });
+                       network.channels.insert(NetworkMap::get_key(11, zero_hash.clone()), ChannelInfo {
+                               features: GlobalFeatures::new(),
+                               one_to_two: DirectionalChannelInfo {
+                                       src_node_id: node5.clone(),
+                                       last_update: 0,
+                                       enabled: true,
+                                       cltv_expiry_delta: (11 << 8) | 1,
+                                       htlc_minimum_msat: 0,
+                                       fee_base_msat: 0,
+                                       fee_proportional_millionths: 0,
+                               }, two_to_one: DirectionalChannelInfo {
+                                       src_node_id: node4.clone(),
+                                       last_update: 0,
+                                       enabled: true,
+                                       cltv_expiry_delta: (11 << 8) | 2,
+                                       htlc_minimum_msat: 0,
+                                       fee_base_msat: 0,
+                                       fee_proportional_millionths: 0,
+                               },
+                       });
+                       network.nodes.insert(node6.clone(), NodeInfo {
+                               channels: vec!(NetworkMap::get_key(7, zero_hash.clone())),
+                               lowest_inbound_channel_fee_base_msat: 0,
+                               lowest_inbound_channel_fee_proportional_millionths: 0,
+                               features: GlobalFeatures::new(),
+                               last_update: 1,
+                               rgb: [0; 3],
+                               alias: [0; 32],
+                               addresses: Vec::new(),
+                       });
+                       network.channels.insert(NetworkMap::get_key(7, zero_hash.clone()), ChannelInfo {
+                               features: GlobalFeatures::new(),
+                               one_to_two: DirectionalChannelInfo {
+                                       src_node_id: node3.clone(),
+                                       last_update: 0,
+                                       enabled: true,
+                                       cltv_expiry_delta: (7 << 8) | 1,
+                                       htlc_minimum_msat: 0,
+                                       fee_base_msat: 0,
+                                       fee_proportional_millionths: 1000000,
+                               }, two_to_one: DirectionalChannelInfo {
+                                       src_node_id: node6.clone(),
+                                       last_update: 0,
+                                       enabled: true,
+                                       cltv_expiry_delta: (7 << 8) | 2,
+                                       htlc_minimum_msat: 0,
+                                       fee_base_msat: 0,
+                                       fee_proportional_millionths: 0,
+                               },
+                       });
+               }
+
+               { // Simple route to 3 via 2
+                       let route = router.get_route(&node3, &Vec::new(), 100, 42).unwrap();
+                       assert_eq!(route.hops.len(), 2);
+
+                       assert_eq!(route.hops[0].pubkey, node2);
+                       assert_eq!(route.hops[0].short_channel_id, 2);
+                       assert_eq!(route.hops[0].fee_msat, 100);
+                       assert_eq!(route.hops[0].cltv_expiry_delta, (4 << 8) | 1);
+
+                       assert_eq!(route.hops[1].pubkey, node3);
+                       assert_eq!(route.hops[1].short_channel_id, 4);
+                       assert_eq!(route.hops[1].fee_msat, 100);
+                       assert_eq!(route.hops[1].cltv_expiry_delta, 42);
+               }
+
+               { // Route to 1 via 2 and 3 because our channel to 1 is disabled
+                       let route = router.get_route(&node1, &Vec::new(), 100, 42).unwrap();
+                       assert_eq!(route.hops.len(), 3);
+
+                       assert_eq!(route.hops[0].pubkey, node2);
+                       assert_eq!(route.hops[0].short_channel_id, 2);
+                       assert_eq!(route.hops[0].fee_msat, 200);
+                       assert_eq!(route.hops[0].cltv_expiry_delta, (4 << 8) | 1);
+
+                       assert_eq!(route.hops[1].pubkey, node3);
+                       assert_eq!(route.hops[1].short_channel_id, 4);
+                       assert_eq!(route.hops[1].fee_msat, 100);
+                       assert_eq!(route.hops[1].cltv_expiry_delta, (3 << 8) | 2);
+
+                       assert_eq!(route.hops[2].pubkey, node1);
+                       assert_eq!(route.hops[2].short_channel_id, 3);
+                       assert_eq!(route.hops[2].fee_msat, 100);
+                       assert_eq!(route.hops[2].cltv_expiry_delta, 42);
+               }
+
+               let mut last_hops = vec!(RouteHint {
+                               src_node_id: node4.clone(),
+                               short_channel_id: 8,
+                               fee_base_msat: 0,
+                               fee_proportional_millionths: 0,
+                               cltv_expiry_delta: (8 << 8) | 1,
+                               htlc_minimum_msat: 0,
+                       }, RouteHint {
+                               src_node_id: node5.clone(),
+                               short_channel_id: 9,
+                               fee_base_msat: 1001,
+                               fee_proportional_millionths: 0,
+                               cltv_expiry_delta: (9 << 8) | 1,
+                               htlc_minimum_msat: 0,
+                       }, RouteHint {
+                               src_node_id: node6.clone(),
+                               short_channel_id: 10,
+                               fee_base_msat: 0,
+                               fee_proportional_millionths: 0,
+                               cltv_expiry_delta: (10 << 8) | 1,
+                               htlc_minimum_msat: 0,
+                       });
+
+               { // Simple test across 2, 3, 5, and 4 via a last_hop channel
+                       let route = router.get_route(&node7, &last_hops, 100, 42).unwrap();
+                       assert_eq!(route.hops.len(), 5);
+
+                       assert_eq!(route.hops[0].pubkey, node2);
+                       assert_eq!(route.hops[0].short_channel_id, 2);
+                       assert_eq!(route.hops[0].fee_msat, 100);
+                       assert_eq!(route.hops[0].cltv_expiry_delta, (4 << 8) | 1);
+
+                       assert_eq!(route.hops[1].pubkey, node3);
+                       assert_eq!(route.hops[1].short_channel_id, 4);
+                       assert_eq!(route.hops[1].fee_msat, 0);
+                       assert_eq!(route.hops[1].cltv_expiry_delta, (6 << 8) | 1);
+
+                       assert_eq!(route.hops[2].pubkey, node5);
+                       assert_eq!(route.hops[2].short_channel_id, 6);
+                       assert_eq!(route.hops[2].fee_msat, 0);
+                       assert_eq!(route.hops[2].cltv_expiry_delta, (11 << 8) | 1);
+
+                       assert_eq!(route.hops[3].pubkey, node4);
+                       assert_eq!(route.hops[3].short_channel_id, 11);
+                       assert_eq!(route.hops[3].fee_msat, 0);
+                       assert_eq!(route.hops[3].cltv_expiry_delta, (8 << 8) | 1);
+
+                       assert_eq!(route.hops[4].pubkey, node7);
+                       assert_eq!(route.hops[4].short_channel_id, 8);
+                       assert_eq!(route.hops[4].fee_msat, 100);
+                       assert_eq!(route.hops[4].cltv_expiry_delta, 42);
+               }
+
+               last_hops[0].fee_base_msat = 1000;
+
+               { // Revert to via 6 as the fee on 8 goes up
+                       let route = router.get_route(&node7, &last_hops, 100, 42).unwrap();
+                       assert_eq!(route.hops.len(), 4);
+
+                       assert_eq!(route.hops[0].pubkey, node2);
+                       assert_eq!(route.hops[0].short_channel_id, 2);
+                       assert_eq!(route.hops[0].fee_msat, 200); // fee increased as its % of value transferred across node
+                       assert_eq!(route.hops[0].cltv_expiry_delta, (4 << 8) | 1);
+
+                       assert_eq!(route.hops[1].pubkey, node3);
+                       assert_eq!(route.hops[1].short_channel_id, 4);
+                       assert_eq!(route.hops[1].fee_msat, 100);
+                       assert_eq!(route.hops[1].cltv_expiry_delta, (7 << 8) | 1);
+
+                       assert_eq!(route.hops[2].pubkey, node6);
+                       assert_eq!(route.hops[2].short_channel_id, 7);
+                       assert_eq!(route.hops[2].fee_msat, 0);
+                       assert_eq!(route.hops[2].cltv_expiry_delta, (10 << 8) | 1);
+
+                       assert_eq!(route.hops[3].pubkey, node7);
+                       assert_eq!(route.hops[3].short_channel_id, 10);
+                       assert_eq!(route.hops[3].fee_msat, 100);
+                       assert_eq!(route.hops[3].cltv_expiry_delta, 42);
+               }
+
+               { // ...but still use 8 for larger payments as 6 has a variable feerate
+                       let route = router.get_route(&node7, &last_hops, 2000, 42).unwrap();
+                       assert_eq!(route.hops.len(), 5);
+
+                       assert_eq!(route.hops[0].pubkey, node2);
+                       assert_eq!(route.hops[0].short_channel_id, 2);
+                       assert_eq!(route.hops[0].fee_msat, 3000);
+                       assert_eq!(route.hops[0].cltv_expiry_delta, (4 << 8) | 1);
+
+                       assert_eq!(route.hops[1].pubkey, node3);
+                       assert_eq!(route.hops[1].short_channel_id, 4);
+                       assert_eq!(route.hops[1].fee_msat, 0);
+                       assert_eq!(route.hops[1].cltv_expiry_delta, (6 << 8) | 1);
+
+                       assert_eq!(route.hops[2].pubkey, node5);
+                       assert_eq!(route.hops[2].short_channel_id, 6);
+                       assert_eq!(route.hops[2].fee_msat, 0);
+                       assert_eq!(route.hops[2].cltv_expiry_delta, (11 << 8) | 1);
+
+                       assert_eq!(route.hops[3].pubkey, node4);
+                       assert_eq!(route.hops[3].short_channel_id, 11);
+                       assert_eq!(route.hops[3].fee_msat, 1000);
+                       assert_eq!(route.hops[3].cltv_expiry_delta, (8 << 8) | 1);
+
+                       assert_eq!(route.hops[4].pubkey, node7);
+                       assert_eq!(route.hops[4].short_channel_id, 8);
+                       assert_eq!(route.hops[4].fee_msat, 2000);
+                       assert_eq!(route.hops[4].cltv_expiry_delta, 42);
+               }
+       }
+}
diff --git a/src/util/byte_utils.rs b/src/util/byte_utils.rs
new file mode 100644 (file)
index 0000000..8779723
--- /dev/null
@@ -0,0 +1,69 @@
+//TODO: Dont expose
+
+#[inline]
+pub fn slice_to_be16(v: &[u8]) -> u16 {
+       ((v[0] as u16) << 8*1) |
+       ((v[1] as u16) << 8*0)
+}
+#[inline]
+pub fn slice_to_be32(v: &[u8]) -> u32 {
+       ((v[0] as u32) << 8*3) |
+       ((v[1] as u32) << 8*2) |
+       ((v[2] as u32) << 8*1) |
+       ((v[3] as u32) << 8*0)
+}
+#[inline]
+pub fn slice_to_be64(v: &[u8]) -> u64 {
+       ((v[0] as u64) << 8*7) |
+       ((v[1] as u64) << 8*6) |
+       ((v[2] as u64) << 8*5) |
+       ((v[3] as u64) << 8*4) |
+       ((v[4] as u64) << 8*3) |
+       ((v[5] as u64) << 8*2) |
+       ((v[6] as u64) << 8*1) |
+       ((v[7] as u64) << 8*0)
+}
+
+#[inline]
+pub fn be16_to_array(u: u16) -> [u8; 2] {
+       let mut v = [0; 2];
+       v[0] = ((u >> 8*1) & 0xff) as u8;
+       v[1] = ((u >> 8*0) & 0xff) as u8;
+       v
+}
+#[inline]
+pub fn be32_to_array(u: u32) -> [u8; 4] {
+       let mut v = [0; 4];
+       v[0] = ((u >> 8*3) & 0xff) as u8;
+       v[1] = ((u >> 8*2) & 0xff) as u8;
+       v[2] = ((u >> 8*1) & 0xff) as u8;
+       v[3] = ((u >> 8*0) & 0xff) as u8;
+       v
+}
+#[inline]
+pub fn be64_to_array(u: u64) -> [u8; 8] {
+       let mut v = [0; 8];
+       v[0] = ((u >> 8*7) & 0xff) as u8;
+       v[1] = ((u >> 8*6) & 0xff) as u8;
+       v[2] = ((u >> 8*5) & 0xff) as u8;
+       v[3] = ((u >> 8*4) & 0xff) as u8;
+       v[4] = ((u >> 8*3) & 0xff) as u8;
+       v[5] = ((u >> 8*2) & 0xff) as u8;
+       v[6] = ((u >> 8*1) & 0xff) as u8;
+       v[7] = ((u >> 8*0) & 0xff) as u8;
+       v
+}
+
+#[inline]
+pub fn le64_to_array(u: u64) -> [u8; 8] {
+       let mut v = [0; 8];
+       v[0] = ((u >> 8*0) & 0xff) as u8;
+       v[1] = ((u >> 8*1) & 0xff) as u8;
+       v[2] = ((u >> 8*2) & 0xff) as u8;
+       v[3] = ((u >> 8*3) & 0xff) as u8;
+       v[4] = ((u >> 8*4) & 0xff) as u8;
+       v[5] = ((u >> 8*5) & 0xff) as u8;
+       v[6] = ((u >> 8*6) & 0xff) as u8;
+       v[7] = ((u >> 8*7) & 0xff) as u8;
+       v
+}
diff --git a/src/util/chacha20poly1305rfc.rs b/src/util/chacha20poly1305rfc.rs
new file mode 100644 (file)
index 0000000..f9391db
--- /dev/null
@@ -0,0 +1,102 @@
+// ring has a garbage API so its use is avoided, but rust-crypto doesn't have RFC-variant poly1305
+// Instead, we steal rust-crypto's implementation and tweak it to match the RFC.
+
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// This is a port of Andrew Moons poly1305-donna
+// https://github.com/floodyberry/poly1305-donna
+
+use crypto::aead::{AeadEncryptor,AeadDecryptor};
+use crypto::chacha20::ChaCha20;
+use crypto::symmetriccipher::SynchronousStreamCipher;
+use crypto::poly1305::Poly1305;
+use crypto::mac::Mac;
+use crypto::util::fixed_time_eq;
+
+use util::byte_utils;
+
+#[derive(Clone, Copy)]
+pub struct ChaCha20Poly1305RFC {
+    cipher  : ChaCha20,
+    mac: Poly1305,
+    finished: bool,
+    data_len: usize,
+    aad_len: u64,
+}
+
+impl ChaCha20Poly1305RFC {
+  #[inline]
+  fn pad_mac_16(mac: &mut Poly1305, len: usize) {
+      if len % 16 != 0 {
+        mac.input(&[0; 16][0..16 - (len % 16)]);
+      }
+  }
+  pub fn new(key: &[u8], nonce: &[u8], aad: &[u8]) -> ChaCha20Poly1305RFC {
+      assert!(key.len() == 16 || key.len() == 32);
+      assert!(nonce.len() == 12);
+
+      // Ehh, I'm too lazy to *also* tweak ChaCha20 to make it RFC-compliant
+      assert!(nonce[0] == 0 && nonce[1] == 0 && nonce[2] == 0 && nonce[3] == 0);
+
+      let mut cipher = ChaCha20::new(key, &nonce[4..]);
+      let mut mac_key = [0u8; 64];
+      let zero_key = [0u8; 64];
+      cipher.process(&zero_key, &mut mac_key);
+
+      let mut mac = Poly1305::new(&mac_key[..32]);
+      mac.input(aad);
+      ChaCha20Poly1305RFC::pad_mac_16(&mut mac, aad.len());
+
+      ChaCha20Poly1305RFC {
+        cipher: cipher,
+        mac: mac,
+        finished: false,
+        data_len: 0,
+        aad_len: aad.len() as u64,
+      }
+  }
+}
+
+impl AeadEncryptor for ChaCha20Poly1305RFC {
+    fn encrypt(&mut self, input: &[u8], output: &mut [u8], out_tag: &mut [u8]) {
+        assert!(input.len() == output.len());
+        assert!(self.finished == false);
+        self.cipher.process(input, output);
+        self.data_len += input.len();
+        self.mac.input(output);
+        ChaCha20Poly1305RFC::pad_mac_16(&mut self.mac, self.data_len);
+        self.finished = true;
+        self.mac.input(&byte_utils::le64_to_array(self.aad_len));
+        self.mac.input(&byte_utils::le64_to_array(self.data_len as u64));
+        self.mac.raw_result(out_tag);
+    }
+}
+
+impl AeadDecryptor for ChaCha20Poly1305RFC {
+    fn decrypt(&mut self, input: &[u8], output: &mut [u8], tag: &[u8]) -> bool {
+        assert!(input.len() == output.len());
+        assert!(self.finished == false);
+
+        self.finished = true;
+
+        self.mac.input(input);
+
+        self.data_len += input.len();
+        ChaCha20Poly1305RFC::pad_mac_16(&mut self.mac, self.data_len);
+        self.mac.input(&byte_utils::le64_to_array(self.aad_len));
+        self.mac.input(&byte_utils::le64_to_array(self.data_len as u64));
+
+        let mut calc_tag =  [0u8; 16];
+        self.mac.raw_result(&mut calc_tag);
+        if fixed_time_eq(&calc_tag, tag) {
+            self.cipher.process(input, output);
+            true
+        } else {
+            false
+        }
+    }
+}
diff --git a/src/util/events.rs b/src/util/events.rs
new file mode 100644 (file)
index 0000000..1bdc368
--- /dev/null
@@ -0,0 +1,77 @@
+use ln::msgs;
+
+use bitcoin::blockdata::script::Script;
+use bitcoin::util::uint::Uint256;
+use bitcoin::util::hash::Sha256dHash;
+
+use secp256k1::key::PublicKey;
+
+use std::time::Instant;
+
+pub enum Event {
+       // Events a user will probably have to handle
+       /// Used to indicate that the client should generate a funding transaction with the given
+       /// parameters and then call ChannelManager::funding_transaction_generated.
+       /// Generated in ChannelManager message handling.
+       FundingGenerationReady {
+               temporary_channel_id: Uint256,
+               channel_value_satoshis: u64,
+               output_script: Script,
+               /// The value passed in to ChannelManager::create_channel
+               user_channel_id: u64,
+       },
+       /// Used to indicate that the client may now broadcast the funding transaction it created for a
+       /// channel. Broadcasting such a transaction prior to this event may lead to our counterparty
+       /// trivially stealing all funds in the funding transaction!
+       FundingBroadcastSafe {
+               funding_txo: (Sha256dHash, u16),
+               /// The value passed in to ChannelManager::create_channel
+               user_channel_id: u64,
+       },
+       /// Indicates we've received money! Just gotta dig out that payment preimage and feed it to
+       /// ChannelManager::claim_funds to get it....
+       PaymentReceived {
+               payment_hash: [u8; 32],
+               amt: u64,
+       },
+
+       // Events indicating the network loop should send a message to a peer:
+       /// Used to indicate that ChannelManager::process_pending_htlc_forwards should be called at a
+       /// time in the future.
+       PendingHTLCsForwardable {
+               time_forwardable: Instant,
+       },
+       /// Used to indicate that a funding_created message should be sent to the peer with the given node_id.
+       SendFundingCreated {
+               node_id: PublicKey,
+               msg: msgs::FundingCreated,
+       },
+       /// Used to indicate that a funding_locked message should be sent to the peer with the given node_id.
+       SendFundingLocked {
+               node_id: PublicKey,
+               msg: msgs::FundingLocked,
+               announcement_sigs: Option<msgs::AnnouncementSignatures>,
+       },
+       /// Used to indicate that a series of update_add_htlc messages, as well as a commitment_signed
+       /// message should be sent to the peer with the given node_id.
+       SendHTLCs {
+               node_id: PublicKey,
+               msgs: Vec<msgs::UpdateAddHTLC>,
+               commitment_msg: msgs::CommitmentSigned,
+       },
+       /// Used to indicate that we're ready to fulfill an htlc from the peer with the given node_id.
+       SendFulfillHTLC {
+               node_id: PublicKey,
+               msg: msgs::UpdateFulfillHTLC,
+       },
+       /// Used to indicate that a channel_announcement and channel_update should be broadcast to all
+       /// peers (except the peer with node_id either msg.contents.node_id_1 or msg.contents.node_id_2).
+       BroadcastChannelAnnouncement {
+               msg: msgs::ChannelAnnouncement,
+               update_msg: msgs::ChannelUpdate,
+       },
+}
+
+pub trait EventsProvider {
+       fn get_and_clear_pending_events(&self) -> Vec<Event>;
+}
diff --git a/src/util/internal_traits.rs b/src/util/internal_traits.rs
new file mode 100644 (file)
index 0000000..c12276c
--- /dev/null
@@ -0,0 +1,7 @@
+/// A simple marker trait that indicates a type requires no deallocation. Implies we can set_len()
+/// on a Vec of these things and will be safe to overwrite them with =.
+pub unsafe trait NoDealloc {}
+
+/// Just call with test_no_dealloc::<Type>(None)
+#[inline]
+pub fn test_no_dealloc<T : NoDealloc>(_: Option<T>) { }
diff --git a/src/util/mod.rs b/src/util/mod.rs
new file mode 100644 (file)
index 0000000..c4fdff5
--- /dev/null
@@ -0,0 +1,9 @@
+pub mod byte_utils;
+pub mod transaction_utils;
+pub mod chacha20poly1305rfc;
+pub mod events;
+
+pub(crate) mod internal_traits;
+
+#[cfg(test)]
+pub(crate) mod test_utils;
diff --git a/src/util/test_utils.rs b/src/util/test_utils.rs
new file mode 100644 (file)
index 0000000..beb5094
--- /dev/null
@@ -0,0 +1,57 @@
+use chain::chaininterface;
+use chain::chaininterface::ConfirmationTarget;
+use ln::channelmonitor;
+use ln::msgs::HandleError;
+
+use bitcoin::util::hash::Sha256dHash;
+use bitcoin::blockdata::transaction::Transaction;
+use bitcoin::blockdata::script::Script;
+
+use std::sync::Weak;
+
+pub struct TestFeeEstimator {
+       pub sat_per_vbyte: u64,
+}
+impl chaininterface::FeeEstimator for TestFeeEstimator {
+       fn get_est_sat_per_vbyte(&self, _confirmation_target: ConfirmationTarget) -> u64 {
+               self.sat_per_vbyte
+       }
+}
+
+pub struct TestWatchInterface {
+       pub watch_util: chaininterface::ChainWatchInterfaceUtil,
+}
+impl chaininterface::ChainWatchInterface for TestWatchInterface {
+       fn install_watch_script(&self, _script_pub_key: Script) {
+               unimplemented!();
+       }
+       fn install_watch_outpoint(&self, _outpoint: (Sha256dHash, u32)) {
+               unimplemented!();
+       }
+       fn watch_all_txn(&self) {
+               unimplemented!();
+       }
+       fn broadcast_transaction(&self, _tx: &Transaction) {
+               unimplemented!();
+       }
+       fn register_listener(&self, listener: Weak<chaininterface::ChainListener>) {
+               self.watch_util.register_listener(listener);
+       }
+}
+impl TestWatchInterface {
+       pub fn new() -> TestWatchInterface {
+               TestWatchInterface {
+                       watch_util: chaininterface::ChainWatchInterfaceUtil::new(),
+               }
+       }
+}
+
+pub struct TestChannelMonitor {
+
+}
+impl channelmonitor::ManyChannelMonitor for TestChannelMonitor {
+       fn add_update_monitor(&self, _funding_txo: (Sha256dHash, u16), _monitor: channelmonitor::ChannelMonitor) -> Result<(), HandleError> {
+               //TODO!
+               Ok(())
+       }
+}
diff --git a/src/util/transaction_utils.rs b/src/util/transaction_utils.rs
new file mode 100644 (file)
index 0000000..d597b77
--- /dev/null
@@ -0,0 +1,19 @@
+use bitcoin::blockdata::transaction::TxOut;
+
+use std::cmp::Ordering;
+
+pub fn sort_outputs<T>(outputs: &mut Vec<(TxOut, T)>) { //TODO: Make static and put it in some utils somewhere (+inputs sorting)
+       outputs.sort_unstable_by(|a, b| {
+               if a.0.value < b.0.value {
+                       Ordering::Less
+               } else if b.0.value < a.0.value {
+                       Ordering::Greater
+               } else if a.0.script_pubkey[..] < b.0.script_pubkey[..] { //TODO: ordering of scripts shouldnt be len-based
+                       Ordering::Less
+               } else if b.0.script_pubkey[..] < a.0.script_pubkey[..] { //TODO: ordering of scripts shouldnt be len-based
+                       Ordering::Greater
+               } else {
+                       Ordering::Equal
+               }
+       });
+}
diff --git a/src/wallet/mod.rs b/src/wallet/mod.rs
new file mode 100644 (file)
index 0000000..0759f54
--- /dev/null
@@ -0,0 +1 @@
+pub mod walletinterface;
diff --git a/src/wallet/walletinterface.rs b/src/wallet/walletinterface.rs
new file mode 100644 (file)
index 0000000..8b13789
--- /dev/null
@@ -0,0 +1 @@
+