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::chan_utils::{TxCreationKeys,HTLCOutputInCommitment};
use ln::chan_utils;
use chain::chaininterface::{FeeEstimator,ConfirmationTarget};
-use util::transaction_utils;
-
-use rand::{thread_rng,Rng};
+use util::{transaction_utils,rng};
+use util::sha2::Sha256;
use std::default::Default;
use std::cmp;
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);
+ hkdf_extract(Sha256::new(), 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(Sha256::new(), &prk, b"rust-lightning funding key info", &mut okm);
+ let funding_key = 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(Sha256::new(), &prk, b"rust-lightning revocation base key info", &mut okm);
+ let revocation_base_key = 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(Sha256::new(), &prk, b"rust-lightning payment base key info", &mut okm);
+ let payment_base_key = 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(Sha256::new(), &prk, b"rust-lightning delayed payment base key info", &mut okm);
+ let delayed_payment_base_key = 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(Sha256::new(), &prk, b"rust-lightning htlc base key info", &mut okm);
+ let htlc_base_key = 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(Sha256::new(), &prk, b"rust-lightning channel close key info", &mut okm);
+ let channel_close_key = SecretKey::from_slice(&secp_ctx, &okm)?;
- hkdf_expand(sha, &prk, b"rust-lightning channel monitor claim key info", &mut okm);
- let channel_monitor_claim_key = try!(SecretKey::from_slice(&secp_ctx, &okm));
+ hkdf_expand(Sha256::new(), &prk, b"rust-lightning channel monitor claim key info", &mut okm);
+ let channel_monitor_claim_key = SecretKey::from_slice(&secp_ctx, &okm)?;
- hkdf_expand(sha, &prk, b"rust-lightning local commitment seed info", &mut okm);
+ hkdf_expand(Sha256::new(), &prk, b"rust-lightning local commitment seed info", &mut okm);
Ok(ChannelKeys {
funding_key: funding_key,
AwaitingRemoteRevoke = (1 << 7),
}
-// TODO: We should refactor this to be a Inbound/OutboundChannel until initial setup handshaking
+// TODO: We should refactor this to be an 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.
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);
+ rng::fill_bytes(&mut key_seed);
let chan_keys = match ChannelKeys::new_from_seed(&key_seed) {
Ok(key) => key,
Err(_) => panic!("RNG is busted!")
Channel {
user_id: user_id,
- channel_id: Uint256([rng.gen(), rng.gen(), rng.gen(), rng.gen()]),
+ channel_id: rng::rand_uint256(),
channel_state: ChannelState::OurInitSent as u32,
channel_outbound: true,
secp_ctx: secp_ctx,
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.dust_limit_satoshis > 21000000 * 100000000 {
+ return Err(HandleError{err: "Peer never wants payout outputs?", msg: None});
+ }
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();
+ Channel::check_remote_fee(fee_estimator, msg.feerate_per_kw)?;
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});
}
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);
+ rng::fill_bytes(&mut key_seed);
let chan_keys = match ChannelKeys::new_from_seed(&key_seed) {
Ok(key) => key,
Err(_) => panic!("RNG is busted!")
/// 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 per_commitment_point = PublicKey::from_secret_key(&self.secp_ctx, &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();
return Err(HandleError{err: "Unable to find a pending HTLC which matched the given payment preimage", msg: None});
}
+ //TODO: This is racy af, they may have pending messages in flight to us that will not have
+ //received this yet!
self.value_to_self_msat += htlc_amount_msat;
-
Ok(msgs::UpdateFulfillHTLC {
channel_id: self.channel_id(),
htlc_id: htlc_id,
})
}
+ pub fn get_update_fail_htlc(&mut self, payment_hash: &[u8; 32], err_packet: msgs::OnionErrorPacket) -> Result<msgs::UpdateFailHTLC, HandleError> {
+ if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) {
+ return Err(HandleError{err: "Was asked to fail an HTLC when channel was not in an operational state", msg: None});
+ }
+
+ 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});
+ }
+
+ //TODO: This is racy af, they may have pending messages in flight to us that will not have
+ //received this yet!
+
+ Ok(msgs::UpdateFailHTLC {
+ channel_id: self.channel_id(),
+ htlc_id,
+ reason: err_packet
+ })
+ }
+
// 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.dust_limit_satoshis > 21000000 * 100000000 {
+ return Err(HandleError{err: "Peer never wants payout outputs?", 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});
}
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_keys = self.build_remote_transaction_keys()?;
+ let remote_initial_commitment_tx = 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_keys = self.build_local_transaction_keys(self.cur_local_commitment_transaction_number)?;
+ let local_initial_commitment_tx = 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.
}
/// Handles a funding_signed message from the remote end.
- /// If this call is successfull, broadcast the funding transaction (and not before!)
+ /// If this call is successful, 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});
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_keys = self.build_local_transaction_keys(self.cur_local_commitment_transaction_number)?;
+ let local_initial_commitment_tx = 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.
}
//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,
+ //as otherwise we will have a commitment transaction that they can't 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 {
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 {
+ // Check our_channel_reserve_satoshis (we're getting paid, so they have to at least meet
+ // the reserve_satoshis we told them to always have as direct payment so that they lose
+ // something if we punish them for broadcasting an old state).
+ if htlc_inbound_value_msat + htlc_outbound_value_msat + msg.amount_msat + self.value_to_self_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 {
}
/// 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> {
+ fn remove_outbound_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 found_idx {
- None => Err(HandleError{err: "Remote tried to fulfill an HTLC we couldn't find", msg: None}),
+ None => Err(HandleError{err: "Remote tried to fulfill/fail an HTLC we couldn't find", msg: None}),
Some(idx) => {
Ok(self.pending_htlcs.swap_remove(idx))
}
//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()))))
+ Ok(Some((update_add_msgs, self.send_commitment()?)))
} else {
Err(err.unwrap())
}
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)) {
+ match self.remove_outbound_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
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> {
+ pub fn update_fail_htlc(&mut self, msg: &msgs::UpdateFailHTLC) -> Result<([u8; 32], 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) {
+ let payment_hash = match self.remove_outbound_htlc(msg.htlc_id, None) {
Err(e) => return Err(e),
- Ok(_htlc) => {
+ Ok(htlc) => {
//TODO: Double-check that we didn't exceed some limits (or value_to_self went
//negative here?)
- ////TODO: Something?
+ htlc.payment_hash
}
- }
+ };
- self.check_and_free_holding_cell_htlcs()
+ let holding_cell_freedom = self.check_and_free_holding_cell_htlcs()?;
+ Ok((payment_hash, holding_cell_freedom))
}
- pub fn update_fail_malformed_htlc(&mut self, msg: &msgs::UpdateFailMalformedHTLC) -> Result<Option<(Vec<msgs::UpdateAddHTLC>, msgs::CommitmentSigned)>, HandleError> {
+ pub fn update_fail_malformed_htlc(&mut self, msg: &msgs::UpdateFailMalformedHTLC) -> Result<([u8; 32], 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) {
+ let payment_hash = match self.remove_outbound_htlc(msg.htlc_id, None) {
Err(e) => return Err(e),
- Ok(_htlc) => {
+ Ok(htlc) => {
//TODO: Double-check that we didn't exceed some limits (or value_to_self went
//negative here?)
- ////TODO: Something?
+ htlc.payment_hash
}
- }
+ };
- self.check_and_free_holding_cell_htlcs()
+ let holding_cell_freedom = self.check_and_free_holding_cell_htlcs()?;
+ Ok((payment_hash, holding_cell_freedom))
}
pub fn commitment_signed(&mut self, msg: &msgs::CommitmentSigned) -> Result<(msgs::RevokeAndACK, Vec<PendingForwardHTLCInfo>), HandleError> {
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_keys = self.build_local_transaction_keys(self.cur_local_commitment_transaction_number)?;
+ let local_commitment_tx = 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));
}
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_tx = 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 next_per_commitment_point = PublicKey::from_secret_key(&self.secp_ctx, &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
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));
+ 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
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,
+ //as otherwise we will have a commitment transaction that they can't 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) {
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));
+ let local_commitment_secret = self.build_local_commitment_secret(self.cur_local_commitment_transaction_number)?;
Ok(msgs::OpenChannel {
chain_hash: chain_hash,
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));
+ let local_commitment_secret = self.build_local_commitment_secret(self.cur_local_commitment_transaction_number)?;
Ok(msgs::AcceptChannel {
temporary_channel_id: self.channel_id,
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_keys = self.build_remote_transaction_keys()?;
+ let remote_initial_commitment_tx = 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.
/// 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!
+ /// Do NOT broadcast the funding transaction until after a successful 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!");
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 {
+ if htlc_inbound_value_msat + htlc_outbound_value_msat + amount_msat + (self.channel_value_satoshis * 1000 - self.value_to_self_msat) > (self.channel_value_satoshis - self.their_channel_reserve_satoshis) * 1000 {
return Err(HandleError{err: "Cannot send value that would put us over our reserve value", 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_keys = self.build_remote_transaction_keys()?;
+ let remote_commitment_tx = 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_tx = 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));
/// 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)) {
+ match 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())))),
+ Ok(Some((update_add_htlc, self.send_commitment()?))),
None => Ok(None)
}
}
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.local_keys.commitment_seed isn't derived in the test vectors :(
chan.channel_monitor.set_funding_info(Sha256dHash::from_hex("8984484a580b825b9972d7adb15050b3ab624ccd731946b3eeddb92f4e7ef6be").unwrap(), 0);