X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fchannel.rs;h=d754b393c389bc441089310c49856005d78066be;hb=9be497cad4b89ddaf5919f99e2ea5ac9a8ab8bd0;hp=b0f8ef9abee0d60441aaf80563098cf43f880bd9;hpb=9dbce1c316f6ebbfb905148b646ae513325fe039;p=rust-lightning diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index b0f8ef9a..d754b393 100644 --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@ -53,19 +53,43 @@ enum InboundHTLCRemovalReason { } enum InboundHTLCState { - /// Added by remote, to be included in next local commitment tx. + /// Offered by remote, to be included in next local commitment tx. I.e., the remote sent an + /// update_add_htlc message for this HTLC. RemoteAnnounced(PendingHTLCStatus), - /// Included in a received commitment_signed message (implying we've revoke_and_ack'ed it), but - /// the remote side hasn't yet revoked their previous state, which we need them to do before we - /// accept this HTLC. Implies AwaitingRemoteRevoke. - /// We also have not yet included this HTLC in a commitment_signed message, and are waiting on - /// a remote revoke_and_ack on a previous state before we can do so. + /// Included in a received commitment_signed message (implying we've + /// revoke_and_ack'd it), but the remote hasn't yet revoked their previous + /// state (see the example below). We have not yet included this HTLC in a + /// commitment_signed message because we are waiting on the remote's + /// aforementioned state revocation. One reason this missing remote RAA + /// (revoke_and_ack) blocks us from constructing a commitment_signed message + /// is because every time we create a new "state", i.e. every time we sign a + /// new commitment tx (see [BOLT #2]), we need a new per_commitment_point, + /// which are provided one-at-a-time in each RAA. E.g., the last RAA they + /// sent provided the per_commitment_point for our current commitment tx. + /// The other reason we should not send a commitment_signed without their RAA + /// is because their RAA serves to ACK our previous commitment_signed. + /// + /// Here's an example of how an HTLC could come to be in this state: + /// remote --> update_add_htlc(prev_htlc) --> local + /// remote --> commitment_signed(prev_htlc) --> local + /// remote <-- revoke_and_ack <-- local + /// remote <-- commitment_signed(prev_htlc) <-- local + /// [note that here, the remote does not respond with a RAA] + /// remote --> update_add_htlc(this_htlc) --> local + /// remote --> commitment_signed(prev_htlc, this_htlc) --> local + /// Now `this_htlc` will be assigned this state. It's unable to be officially + /// accepted, i.e. included in a commitment_signed, because we're missing the + /// RAA that provides our next per_commitment_point. The per_commitment_point + /// is used to derive commitment keys, which are used to construct the + /// signatures in a commitment_signed message. + /// Implies AwaitingRemoteRevoke. + /// [BOLT #2]: https://github.com/lightningnetwork/lightning-rfc/blob/master/02-peer-protocol.md AwaitingRemoteRevokeToAnnounce(PendingHTLCStatus), - /// Included in a received commitment_signed message (implying we've revoke_and_ack'ed it), but - /// the remote side hasn't yet revoked their previous state, which we need them to do before we - /// accept this HTLC. Implies AwaitingRemoteRevoke. - /// We have included this HTLC in our latest commitment_signed and are now just waiting on a - /// revoke_and_ack. + /// Included in a received commitment_signed message (implying we've revoke_and_ack'd it). + /// We have also included this HTLC in our latest commitment_signed and are now just waiting + /// on the remote's revoke_and_ack to make this HTLC an irrevocable part of the state of the + /// channel (before it can then get forwarded and/or removed). + /// Implies AwaitingRemoteRevoke. AwaitingAnnouncedRemoteRevoke(PendingHTLCStatus), Committed, /// Removed by us and a new commitment_signed was sent (if we were AwaitingRemoteRevoke when we @@ -766,15 +790,14 @@ impl Channel { fn get_commitment_transaction_number_obscure_factor(&self) -> u64 { let mut sha = Sha256::engine(); - let our_payment_point = PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.payment_key()); let their_payment_point = &self.their_pubkeys.as_ref().unwrap().payment_point.serialize(); if self.channel_outbound { - sha.input(&our_payment_point.serialize()); + sha.input(&self.local_keys.pubkeys().payment_point.serialize()); sha.input(their_payment_point); } else { sha.input(their_payment_point); - sha.input(&our_payment_point.serialize()); + sha.input(&self.local_keys.pubkeys().payment_point.serialize()); } let res = Sha256::from_engine(sha).into_inner(); @@ -1095,11 +1118,11 @@ impl Channel { /// TODO Some magic rust shit to compile-time check this? fn build_local_transaction_keys(&self, commitment_number: u64) -> Result { let per_commitment_point = PublicKey::from_secret_key(&self.secp_ctx, &self.build_local_commitment_secret(commitment_number)); - let delayed_payment_base = PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.delayed_payment_base_key()); - let htlc_basepoint = PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.htlc_base_key()); + let delayed_payment_base = &self.local_keys.pubkeys().delayed_payment_basepoint; + let htlc_basepoint = &self.local_keys.pubkeys().htlc_basepoint; let their_pubkeys = self.their_pubkeys.as_ref().unwrap(); - Ok(secp_check!(TxCreationKeys::new(&self.secp_ctx, &per_commitment_point, &delayed_payment_base, &htlc_basepoint, &their_pubkeys.revocation_basepoint, &their_pubkeys.htlc_basepoint), "Local tx keys generation got bogus keys")) + Ok(secp_check!(TxCreationKeys::new(&self.secp_ctx, &per_commitment_point, delayed_payment_base, htlc_basepoint, &their_pubkeys.revocation_basepoint, &their_pubkeys.htlc_basepoint), "Local tx keys generation got bogus keys")) } #[inline] @@ -1109,19 +1132,18 @@ impl Channel { fn build_remote_transaction_keys(&self) -> Result { //TODO: Ensure that the payment_key derived here ends up in the library users' wallet as we //may see payments to it! - let revocation_basepoint = PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.revocation_base_key()); - let htlc_basepoint = PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.htlc_base_key()); + let revocation_basepoint = &self.local_keys.pubkeys().revocation_basepoint; + let htlc_basepoint = &self.local_keys.pubkeys().htlc_basepoint; let their_pubkeys = self.their_pubkeys.as_ref().unwrap(); - Ok(secp_check!(TxCreationKeys::new(&self.secp_ctx, &self.their_cur_commitment_point.unwrap(), &their_pubkeys.delayed_payment_basepoint, &their_pubkeys.htlc_basepoint, &revocation_basepoint, &htlc_basepoint), "Remote tx keys generation got bogus keys")) + Ok(secp_check!(TxCreationKeys::new(&self.secp_ctx, &self.their_cur_commitment_point.unwrap(), &their_pubkeys.delayed_payment_basepoint, &their_pubkeys.htlc_basepoint, revocation_basepoint, htlc_basepoint), "Remote tx keys generation got bogus keys")) } /// Gets the redeemscript for the funding transaction output (ie the funding transaction output /// pays to get_funding_redeemscript().to_v0_p2wsh()). /// Panics if called before accept_channel/new_from_req pub fn get_funding_redeemscript(&self) -> Script { - let our_funding_key = PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.funding_key()); - make_funding_redeemscript(&our_funding_key, self.their_funding_pubkey()) + make_funding_redeemscript(&self.local_keys.pubkeys().funding_pubkey, self.their_funding_pubkey()) } /// Builds the htlc-success or htlc-timeout transaction which spends a given HTLC output @@ -1455,7 +1477,7 @@ impl Channel { log_trace!(logger, "Checking funding_created tx signature {} by key {} against tx {} (sighash {}) with redeemscript {}", log_bytes!(sig.serialize_compact()[..]), log_bytes!(self.their_funding_pubkey().serialize()), encode::serialize_hex(&local_initial_commitment_tx), log_bytes!(local_sighash[..]), encode::serialize_hex(&funding_script)); secp_check!(self.secp_ctx.verify(&local_sighash, &sig, self.their_funding_pubkey()), "Invalid funding_created signature from peer"); - let localtx = LocalCommitmentTransaction::new_missing_local_sig(local_initial_commitment_tx, sig.clone(), &PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.funding_key()), self.their_funding_pubkey(), local_keys, self.feerate_per_kw, Vec::new()); + let localtx = LocalCommitmentTransaction::new_missing_local_sig(local_initial_commitment_tx, sig.clone(), &self.local_keys.pubkeys().funding_pubkey, self.their_funding_pubkey(), local_keys, self.feerate_per_kw, Vec::new()); 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, self.feerate_per_kw, logger).0; @@ -1486,7 +1508,7 @@ impl Channel { panic!("Should not have advanced channel commitment tx numbers prior to funding_created"); } - let funding_txo = OutPoint::new(msg.funding_txid, msg.funding_output_index); + let funding_txo = OutPoint{ txid: msg.funding_txid, index: msg.funding_output_index }; self.funding_txo = Some(funding_txo.clone()); let (remote_initial_commitment_tx, local_initial_commitment_tx, our_signature) = match self.funding_created_signature(&msg.signature, logger) { @@ -1568,7 +1590,7 @@ impl Channel { let funding_txo_script = funding_redeemscript.to_v0_p2wsh(); macro_rules! create_monitor { () => { { - let local_commitment_tx = LocalCommitmentTransaction::new_missing_local_sig(local_initial_commitment_tx.clone(), msg.signature.clone(), &PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.funding_key()), their_funding_pubkey, local_keys.clone(), self.feerate_per_kw, Vec::new()); + let local_commitment_tx = LocalCommitmentTransaction::new_missing_local_sig(local_initial_commitment_tx.clone(), msg.signature.clone(), &self.local_keys.pubkeys().funding_pubkey, their_funding_pubkey, local_keys.clone(), self.feerate_per_kw, Vec::new()); let mut channel_monitor = ChannelMonitor::new(self.local_keys.clone(), &self.shutdown_pubkey, self.our_to_self_delay, &self.destination_script, (funding_txo.clone(), funding_txo_script.clone()), @@ -1899,7 +1921,7 @@ impl Channel { let mut monitor_update = ChannelMonitorUpdate { update_id: self.latest_monitor_update_id, updates: vec![ChannelMonitorUpdateStep::LatestLocalCommitmentTXInfo { - commitment_tx: LocalCommitmentTransaction::new_missing_local_sig(local_commitment_tx.0, msg.signature.clone(), &PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.funding_key()), &their_funding_pubkey, local_keys, self.feerate_per_kw, htlcs_without_source), + commitment_tx: LocalCommitmentTransaction::new_missing_local_sig(local_commitment_tx.0, msg.signature.clone(), &self.local_keys.pubkeys().funding_pubkey, &their_funding_pubkey, local_keys, self.feerate_per_kw, htlcs_without_source), htlc_outputs: htlcs_and_sigs }] }; @@ -2825,7 +2847,7 @@ impl Channel { tx.input[0].witness.push(Vec::new()); // First is the multisig dummy - let our_funding_key = PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.funding_key()).serialize(); + let our_funding_key = self.local_keys.pubkeys().funding_pubkey.serialize(); let their_funding_key = self.their_funding_pubkey().serialize(); if our_funding_key[..] < their_funding_key[..] { tx.input[0].witness.push(our_sig.serialize_der().to_vec()); @@ -3302,6 +3324,7 @@ impl Channel { } let local_commitment_secret = self.build_local_commitment_secret(self.cur_local_commitment_transaction_number); + let local_keys = self.local_keys.pubkeys(); msgs::OpenChannel { chain_hash: chain_hash, @@ -3315,11 +3338,11 @@ impl Channel { feerate_per_kw: fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Background) as u32, to_self_delay: self.our_to_self_delay, max_accepted_htlcs: OUR_MAX_HTLCS, - funding_pubkey: PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.funding_key()), - revocation_basepoint: PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.revocation_base_key()), - payment_point: PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.payment_key()), - delayed_payment_basepoint: PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.delayed_payment_base_key()), - htlc_basepoint: PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.htlc_base_key()), + funding_pubkey: local_keys.funding_pubkey, + revocation_basepoint: local_keys.revocation_basepoint, + payment_point: local_keys.payment_point, + delayed_payment_basepoint: local_keys.delayed_payment_basepoint, + htlc_basepoint: local_keys.htlc_basepoint, first_per_commitment_point: PublicKey::from_secret_key(&self.secp_ctx, &local_commitment_secret), channel_flags: if self.config.announced_channel {1} else {0}, shutdown_scriptpubkey: OptionalField::Present(if self.config.commit_upfront_shutdown_pubkey { self.get_closing_scriptpubkey() } else { Builder::new().into_script() }) @@ -3338,6 +3361,7 @@ impl Channel { } let local_commitment_secret = self.build_local_commitment_secret(self.cur_local_commitment_transaction_number); + let local_keys = self.local_keys.pubkeys(); msgs::AcceptChannel { temporary_channel_id: self.channel_id, @@ -3348,11 +3372,11 @@ impl Channel { minimum_depth: self.minimum_depth, to_self_delay: self.our_to_self_delay, max_accepted_htlcs: OUR_MAX_HTLCS, - funding_pubkey: PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.funding_key()), - revocation_basepoint: PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.revocation_base_key()), - payment_point: PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.payment_key()), - delayed_payment_basepoint: PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.delayed_payment_base_key()), - htlc_basepoint: PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.htlc_base_key()), + funding_pubkey: local_keys.funding_pubkey, + revocation_basepoint: local_keys.revocation_basepoint, + payment_point: local_keys.payment_point, + delayed_payment_basepoint: local_keys.delayed_payment_basepoint, + htlc_basepoint: local_keys.htlc_basepoint, first_per_commitment_point: PublicKey::from_secret_key(&self.secp_ctx, &local_commitment_secret), shutdown_scriptpubkey: OptionalField::Present(if self.config.commit_upfront_shutdown_pubkey { self.get_closing_scriptpubkey() } else { Builder::new().into_script() }) } @@ -3431,7 +3455,6 @@ impl Channel { } 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()); let msg = msgs::UnsignedChannelAnnouncement { features: ChannelFeatures::known(), @@ -3439,8 +3462,8 @@ impl Channel { 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().clone() }, - bitcoin_key_2: if were_node_one { self.their_funding_pubkey().clone() } else { our_bitcoin_key }, + bitcoin_key_1: if were_node_one { self.local_keys.pubkeys().funding_pubkey } else { self.their_funding_pubkey().clone() }, + bitcoin_key_2: if were_node_one { self.their_funding_pubkey().clone() } else { self.local_keys.pubkeys().funding_pubkey }, excess_data: Vec::new(), }; @@ -4387,7 +4410,7 @@ mod tests { let tx = Transaction { version: 1, lock_time: 0, input: Vec::new(), output: vec![TxOut { value: 10000000, script_pubkey: output_script.clone(), }]}; - let funding_outpoint = OutPoint::new(tx.txid(), 0); + let funding_outpoint = OutPoint{ txid: tx.txid(), index: 0 }; let funding_created_msg = node_a_chan.get_outbound_funding_created(funding_outpoint, &&logger).unwrap(); let (funding_signed_msg, _) = node_b_chan.funding_created(&funding_created_msg, &&logger).unwrap(); @@ -4442,7 +4465,7 @@ mod tests { (0, 0) ); - assert_eq!(PublicKey::from_secret_key(&secp_ctx, chan_keys.funding_key()).serialize()[..], + assert_eq!(chan_keys.pubkeys().funding_pubkey.serialize()[..], hex::decode("023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb").unwrap()[..]); let keys_provider = Keys { chan_keys: chan_keys.clone() }; @@ -4453,7 +4476,7 @@ mod tests { chan.their_to_self_delay = 144; chan.our_dust_limit_satoshis = 546; - let funding_info = OutPoint::new(Txid::from_hex("8984484a580b825b9972d7adb15050b3ab624ccd731946b3eeddb92f4e7ef6be").unwrap(), 0); + let funding_info = OutPoint{ txid: Txid::from_hex("8984484a580b825b9972d7adb15050b3ab624ccd731946b3eeddb92f4e7ef6be").unwrap(), index: 0 }; chan.funding_txo = Some(funding_info); let their_pubkeys = ChannelPublicKeys { @@ -4477,11 +4500,11 @@ mod tests { // 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()); + let delayed_payment_base = &chan.local_keys.pubkeys().delayed_payment_basepoint; let per_commitment_secret = SecretKey::from_slice(&hex::decode("1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100").unwrap()[..]).unwrap(); let per_commitment_point = PublicKey::from_secret_key(&secp_ctx, &per_commitment_secret); - let htlc_basepoint = PublicKey::from_secret_key(&secp_ctx, chan.local_keys.htlc_base_key()); - let keys = TxCreationKeys::new(&secp_ctx, &per_commitment_point, &delayed_payment_base, &htlc_basepoint, &their_pubkeys.revocation_basepoint, &their_pubkeys.htlc_basepoint).unwrap(); + let htlc_basepoint = &chan.local_keys.pubkeys().htlc_basepoint; + let keys = TxCreationKeys::new(&secp_ctx, &per_commitment_point, delayed_payment_base, htlc_basepoint, &their_pubkeys.revocation_basepoint, &their_pubkeys.htlc_basepoint).unwrap(); chan.their_pubkeys = Some(their_pubkeys); @@ -4512,7 +4535,7 @@ mod tests { })* assert_eq!(unsigned_tx.1.len(), per_htlc.len()); - localtx = LocalCommitmentTransaction::new_missing_local_sig(unsigned_tx.0.clone(), their_signature.clone(), &PublicKey::from_secret_key(&secp_ctx, chan.local_keys.funding_key()), chan.their_funding_pubkey(), keys.clone(), chan.feerate_per_kw, per_htlc); + localtx = LocalCommitmentTransaction::new_missing_local_sig(unsigned_tx.0.clone(), their_signature.clone(), &chan_keys.pubkeys().funding_pubkey, chan.their_funding_pubkey(), keys.clone(), chan.feerate_per_kw, per_htlc); let local_sig = chan_keys.sign_local_commitment(&localtx, &chan.secp_ctx).unwrap(); assert_eq!(Signature::from_der(&hex::decode($our_sig_hex).unwrap()[..]).unwrap(), local_sig);