X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=src%2Fln%2Fchannel.rs;h=ded81f60c200f23506f3d0df3e48b32233f2aeca;hb=dee4ce5171c0f8e1fd82cc3f8b55174138a6abca;hp=059fc79114490f6a829d23f05bafbba863afe4bf;hpb=5fa80d022ab5249bb7f20f62aa227676247ca821;p=rust-lightning diff --git a/src/ln/channel.rs b/src/ln/channel.rs index 059fc791..ded81f60 100644 --- a/src/ln/channel.rs +++ b/src/ln/channel.rs @@ -245,6 +245,10 @@ pub struct Channel { local_keys: ChannelKeys, + // Our commitment numbers start at 2^48-1 and count down, whereas the ones used in transaction + // generation start at 0 and count up...this simplifies some parts of implementation at the + // cost of others, but should really just be changed. + cur_local_commitment_transaction_number: u64, cur_remote_commitment_transaction_number: u64, value_to_self_msat: u64, // Excluding all pending_htlcs, excluding fees @@ -316,6 +320,9 @@ const COMMITMENT_TX_BASE_WEIGHT: u64 = 724; const COMMITMENT_TX_WEIGHT_PER_HTLC: u64 = 172; 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?) +/// Maximmum `funding_satoshis` value, according to the BOLT #2 specification +/// it's 2^24. +pub const MAX_FUNDING_SATOSHIS: u64 = (1 << 24); macro_rules! secp_call { ( $res: expr, $err: expr ) => { @@ -340,7 +347,7 @@ impl Channel { /// 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 + cmp::min(channel_value_satoshis, 1000) //TODO } fn derive_our_dust_limit_satoshis(at_open_background_feerate: u64) -> u64 { @@ -353,9 +360,9 @@ impl Channel { // Constructors: - /// panics if channel_value_satoshis is >= (1 << 24) + /// panics if channel_value_satoshis is >= `MAX_FUNDING_SATOSHIS` pub fn new_outbound(fee_estimator: &FeeEstimator, chan_keys: ChannelKeys, their_node_id: PublicKey, channel_value_satoshis: u64, announce_publicly: bool, user_id: u64) -> Channel { - if channel_value_satoshis >= (1 << 24) { + if channel_value_satoshis >= MAX_FUNDING_SATOSHIS { panic!("funding value > 2^24"); } @@ -441,12 +448,9 @@ impl Channel { /// that we're rejecting the new channel. pub fn new_from_req(fee_estimator: &FeeEstimator, chan_keys: ChannelKeys, their_node_id: PublicKey, msg: &msgs::OpenChannel, user_id: u64, announce_publicly: bool) -> Result { // Check sanity of message fields: - if msg.funding_satoshis >= (1 << 24) { + if msg.funding_satoshis >= MAX_FUNDING_SATOSHIS { return Err(HandleError{err: "funding value > 2^24", msg: Some(msgs::ErrorAction::DisconnectPeer{})}); } - if msg.funding_satoshis > 21000000 * 100000000 { - return Err(HandleError{err: "More funding_satoshis than there are satoshis!", msg: Some(msgs::ErrorAction::DisconnectPeer{})}); - } if msg.channel_reserve_satoshis > msg.funding_satoshis { return Err(HandleError{err: "Bogus channel_reserve_satoshis", msg: Some(msgs::ErrorAction::DisconnectPeer{})}); } @@ -456,9 +460,6 @@ impl Channel { if msg.dust_limit_satoshis > msg.funding_satoshis { return Err(HandleError{err: "Peer never wants payout outputs?", msg: Some(msgs::ErrorAction::DisconnectPeer{})}); } - if msg.max_htlc_value_in_flight_msat > msg.funding_satoshis * 1000 { - return Err(HandleError{err: "Bogus max_htlc_value_in_flight_satoshis", msg: Some(msgs::ErrorAction::DisconnectPeer{})}); - } 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: Some(msgs::ErrorAction::DisconnectPeer{})}); } @@ -521,7 +522,7 @@ impl Channel { 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_max_htlc_value_in_flight_msat: cmp::min(msg.max_htlc_value_in_flight_msat, msg.funding_satoshis * 1000), 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), @@ -595,7 +596,7 @@ impl Channel { /// 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) -> (Transaction, Vec) { - let obscured_commitment_transaction_number = self.get_commitment_transaction_number_obscure_factor() ^ commitment_number; + let obscured_commitment_transaction_number = self.get_commitment_transaction_number_obscure_factor() ^ (0xffffffffffff - commitment_number); let txins = { let mut ins: Vec = Vec::new(); @@ -1081,9 +1082,6 @@ impl Channel { 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}); - } if msg.channel_reserve_satoshis > self.channel_value_satoshis { return Err(HandleError{err: "Bogus channel_reserve_satoshis", msg: None}); } @@ -1101,7 +1099,7 @@ impl Channel { 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_max_htlc_value_in_flight_msat = cmp::min(msg.max_htlc_value_in_flight_msat, self.channel_value_satoshis * 1000); 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; @@ -1152,7 +1150,8 @@ impl Channel { } let funding_txo = OutPoint::new(msg.funding_txid, msg.funding_output_index); - self.channel_monitor.set_funding_info(funding_txo); + let funding_txo_script = self.get_funding_redeemscript().to_v0_p2wsh(); + self.channel_monitor.set_funding_info((funding_txo, funding_txo_script)); let (remote_initial_commitment_tx, our_signature) = match self.funding_created_signature(&msg.signature) { Ok(res) => res, @@ -2055,7 +2054,8 @@ impl Channel { panic!("Should not have advanced channel commitment tx numbers prior to funding_created"); } - self.channel_monitor.set_funding_info(funding_txo); + let funding_txo_script = self.get_funding_redeemscript().to_v0_p2wsh(); + self.channel_monitor.set_funding_info((funding_txo, funding_txo_script)); let (our_signature, commitment_tx) = match self.get_outbound_funding_created_signature() { Ok(res) => res, @@ -2326,8 +2326,10 @@ mod tests { use bitcoin::util::hash::Sha256dHash; use bitcoin::util::bip143; use bitcoin::network::serialize::serialize; + use bitcoin::blockdata::script::Script; use bitcoin::blockdata::transaction::Transaction; use ln::channel::{Channel,ChannelKeys,HTLCOutput,HTLCState,HTLCOutputInCommitment,TxCreationKeys}; + use ln::channel::MAX_FUNDING_SATOSHIS; use ln::chan_utils; use chain::chaininterface::{FeeEstimator,ConfirmationTarget}; use chain::transaction::OutPoint; @@ -2345,6 +2347,12 @@ mod tests { } } + #[test] + fn test_max_funding_satoshis() { + assert!(MAX_FUNDING_SATOSHIS <= 21_000_000 * 100_000_000, + "MAX_FUNDING_SATOSHIS is greater than all satoshis on existence"); + } + #[test] fn outbound_commitment_test() { // Test vectors from BOLT 3 Appendix C: @@ -2371,7 +2379,7 @@ mod tests { chan.our_dust_limit_satoshis = 546; let funding_info = OutPoint::new(Sha256dHash::from_hex("8984484a580b825b9972d7adb15050b3ab624ccd731946b3eeddb92f4e7ef6be").unwrap(), 0); - chan.channel_monitor.set_funding_info(funding_info); + chan.channel_monitor.set_funding_info((funding_info, Script::new())); 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()[..], @@ -2400,7 +2408,7 @@ mod tests { 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); + unsigned_tx = chan.build_commitment_transaction(0xffffffffffff - 42, &keys, true, false); 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.input[0], &chan.get_funding_redeemscript(), chan.channel_value_satoshis)[..]).unwrap(); secp_ctx.verify(&sighash, &their_signature, &chan.their_funding_pubkey).unwrap();