From 1d7c4f663c41b13ed4a8b67d69c23136442a9b6b Mon Sep 17 00:00:00 2001 From: Antoine Riard Date: Thu, 28 May 2020 20:32:46 -0400 Subject: [PATCH] Change variable nomenclature in chan_utils Variables should be named according to the script semantic which is an invariant with regards to generating a local or remote commitment transaction. I.e a broadcaster_htlc_key will always guard a HTLC to the party able to broadcast the computed transactions whereas countersignatory_htlc_key will guard HTLC to a countersignatory of the commitment transaction. --- .../src/chain/keysinterface.rs | 10 +- lightning-c-bindings/src/ln/chan_utils.rs | 44 +++---- lightning/src/chain/keysinterface.rs | 38 +++--- lightning/src/ln/chan_utils.rs | 113 ++++++++++-------- lightning/src/ln/channel.rs | 22 ++-- lightning/src/ln/channelmonitor.rs | 12 +- lightning/src/ln/functional_tests.rs | 2 +- lightning/src/ln/onchaintx.rs | 6 +- lightning/src/util/enforcing_trait_impls.rs | 6 +- 9 files changed, 133 insertions(+), 120 deletions(-) diff --git a/lightning-c-bindings/src/chain/keysinterface.rs b/lightning-c-bindings/src/chain/keysinterface.rs index 9cc9360bd..5443e4e76 100644 --- a/lightning-c-bindings/src/chain/keysinterface.rs +++ b/lightning-c-bindings/src/chain/keysinterface.rs @@ -357,7 +357,7 @@ pub struct ChannelKeys { /// We bind local_to_self_delay late here for API convenience. /// /// Will be called before any signatures are applied. - pub on_accept: extern "C" fn (this_arg: *mut c_void, channel_points: &crate::ln::chan_utils::ChannelPublicKeys, remote_to_self_delay: u16, local_to_self_delay: u16), + pub on_accept: extern "C" fn (this_arg: *mut c_void, channel_points: &crate::ln::chan_utils::ChannelPublicKeys, counterparty_to_self_delay: u16, local_to_self_delay: u16), pub clone: Option *mut c_void>, pub free: Option, } @@ -447,8 +447,8 @@ impl rustChannelKeys for ChannelKeys { let mut local_ret = match ret.result_ok { true => Ok( { (*unsafe { Box::from_raw(ret.contents.result.take_ptr()) }).into_rust() }), false => Err( { () /*(*unsafe { Box::from_raw(ret.contents.err.take_ptr()) })*/ })}; local_ret } - fn on_accept(&mut self, channel_points: &lightning::ln::chan_utils::ChannelPublicKeys, remote_to_self_delay: u16, local_to_self_delay: u16) { - (self.on_accept)(self.this_arg, &crate::ln::chan_utils::ChannelPublicKeys { inner: unsafe { (channel_points as *const _) as *mut _ }, is_owned: false }, remote_to_self_delay, local_to_self_delay) + fn on_accept(&mut self, channel_points: &lightning::ln::chan_utils::ChannelPublicKeys, counterparty_to_self_delay: u16, local_to_self_delay: u16) { + (self.on_accept)(self.this_arg, &crate::ln::chan_utils::ChannelPublicKeys { inner: unsafe { (channel_points as *const _) as *mut _ }, is_owned: false }, counterparty_to_self_delay, local_to_self_delay) } } @@ -682,8 +682,8 @@ pub extern "C" fn InMemoryChannelKeys_remote_pubkeys(this_arg: &InMemoryChannelK /// Will panic if on_accept wasn't called. #[must_use] #[no_mangle] -pub extern "C" fn InMemoryChannelKeys_remote_to_self_delay(this_arg: &InMemoryChannelKeys) -> u16 { - let mut ret = unsafe { &*this_arg.inner }.remote_to_self_delay(); +pub extern "C" fn InMemoryChannelKeys_counterparty_to_self_delay(this_arg: &InMemoryChannelKeys) -> u16 { + let mut ret = unsafe { &*this_arg.inner }.counterparty_to_self_delay(); ret } diff --git a/lightning-c-bindings/src/ln/chan_utils.rs b/lightning-c-bindings/src/ln/chan_utils.rs index df9094a51..241e35036 100644 --- a/lightning-c-bindings/src/ln/chan_utils.rs +++ b/lightning-c-bindings/src/ln/chan_utils.rs @@ -143,48 +143,48 @@ pub extern "C" fn TxCreationKeys_get_revocation_key(this_ptr: &TxCreationKeys) - pub extern "C" fn TxCreationKeys_set_revocation_key(this_ptr: &mut TxCreationKeys, mut val: crate::c_types::PublicKey) { unsafe { &mut *this_ptr.inner }.revocation_key = val.into_rust(); } -/// A's HTLC Key +/// Broadcaster's HTLC Key #[no_mangle] -pub extern "C" fn TxCreationKeys_get_a_htlc_key(this_ptr: &TxCreationKeys) -> crate::c_types::PublicKey { - let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.a_htlc_key; +pub extern "C" fn TxCreationKeys_get_broadcaster_htlc_key(this_ptr: &TxCreationKeys) -> crate::c_types::PublicKey { + let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.broadcaster_htlc_key; crate::c_types::PublicKey::from_rust(&(*inner_val)) } -/// A's HTLC Key +/// Broadcaster's HTLC Key #[no_mangle] -pub extern "C" fn TxCreationKeys_set_a_htlc_key(this_ptr: &mut TxCreationKeys, mut val: crate::c_types::PublicKey) { - unsafe { &mut *this_ptr.inner }.a_htlc_key = val.into_rust(); +pub extern "C" fn TxCreationKeys_set_broadcaster_htlc_key(this_ptr: &mut TxCreationKeys, mut val: crate::c_types::PublicKey) { + unsafe { &mut *this_ptr.inner }.broadcaster_htlc_key = val.into_rust(); } -/// B's HTLC Key +/// Countersignatory's HTLC Key #[no_mangle] -pub extern "C" fn TxCreationKeys_get_b_htlc_key(this_ptr: &TxCreationKeys) -> crate::c_types::PublicKey { - let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.b_htlc_key; +pub extern "C" fn TxCreationKeys_get_countersignatory_htlc_key(this_ptr: &TxCreationKeys) -> crate::c_types::PublicKey { + let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.countersignatory_htlc_key; crate::c_types::PublicKey::from_rust(&(*inner_val)) } -/// B's HTLC Key +/// Countersignatory's HTLC Key #[no_mangle] -pub extern "C" fn TxCreationKeys_set_b_htlc_key(this_ptr: &mut TxCreationKeys, mut val: crate::c_types::PublicKey) { - unsafe { &mut *this_ptr.inner }.b_htlc_key = val.into_rust(); +pub extern "C" fn TxCreationKeys_set_countersignatory_htlc_key(this_ptr: &mut TxCreationKeys, mut val: crate::c_types::PublicKey) { + unsafe { &mut *this_ptr.inner }.countersignatory_htlc_key = val.into_rust(); } -/// A's Payment Key (which isn't allowed to be spent from for some delay) +/// Payment Key (which isn't allowed to be spent from for some delay) #[no_mangle] -pub extern "C" fn TxCreationKeys_get_a_delayed_payment_key(this_ptr: &TxCreationKeys) -> crate::c_types::PublicKey { - let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.a_delayed_payment_key; +pub extern "C" fn TxCreationKeys_get_delayed_payment_key(this_ptr: &TxCreationKeys) -> crate::c_types::PublicKey { + let mut inner_val = &mut unsafe { &mut *this_ptr.inner }.delayed_payment_key; crate::c_types::PublicKey::from_rust(&(*inner_val)) } -/// A's Payment Key (which isn't allowed to be spent from for some delay) +/// Payment Key (which isn't allowed to be spent from for some delay) #[no_mangle] -pub extern "C" fn TxCreationKeys_set_a_delayed_payment_key(this_ptr: &mut TxCreationKeys, mut val: crate::c_types::PublicKey) { - unsafe { &mut *this_ptr.inner }.a_delayed_payment_key = val.into_rust(); +pub extern "C" fn TxCreationKeys_set_delayed_payment_key(this_ptr: &mut TxCreationKeys, mut val: crate::c_types::PublicKey) { + unsafe { &mut *this_ptr.inner }.delayed_payment_key = val.into_rust(); } #[must_use] #[no_mangle] -pub extern "C" fn TxCreationKeys_new(mut per_commitment_point_arg: crate::c_types::PublicKey, mut revocation_key_arg: crate::c_types::PublicKey, mut a_htlc_key_arg: crate::c_types::PublicKey, mut b_htlc_key_arg: crate::c_types::PublicKey, mut a_delayed_payment_key_arg: crate::c_types::PublicKey) -> TxCreationKeys { +pub extern "C" fn TxCreationKeys_new(mut per_commitment_point_arg: crate::c_types::PublicKey, mut revocation_key_arg: crate::c_types::PublicKey, mut broadcaster_htlc_key_arg: crate::c_types::PublicKey, mut countersignatory_htlc_key_arg: crate::c_types::PublicKey, mut delayed_payment_key_arg: crate::c_types::PublicKey) -> TxCreationKeys { TxCreationKeys { inner: Box::into_raw(Box::new(nativeTxCreationKeys { per_commitment_point: per_commitment_point_arg.into_rust(), revocation_key: revocation_key_arg.into_rust(), - a_htlc_key: a_htlc_key_arg.into_rust(), - b_htlc_key: b_htlc_key_arg.into_rust(), - a_delayed_payment_key: a_delayed_payment_key_arg.into_rust(), + broadcaster_htlc_key: broadcaster_htlc_key_arg.into_rust(), + countersignatory_htlc_key: countersignatory_htlc_key_arg.into_rust(), + delayed_payment_key: delayed_payment_key_arg.into_rust(), })), is_owned: true } } #[no_mangle] diff --git a/lightning/src/chain/keysinterface.rs b/lightning/src/chain/keysinterface.rs index 3c115bc77..9ae939543 100644 --- a/lightning/src/chain/keysinterface.rs +++ b/lightning/src/chain/keysinterface.rs @@ -319,13 +319,13 @@ pub trait ChannelKeys : Send+Clone { /// protocol. fn sign_channel_announcement(&self, msg: &UnsignedChannelAnnouncement, secp_ctx: &Secp256k1) -> Result; - /// Set the remote channel basepoints and remote/local to_self_delay. + /// Set the remote channel basepoints and counterparty/local_to_self_delay. /// This is done immediately on incoming channels and as soon as the channel is accepted on outgoing channels. /// /// We bind local_to_self_delay late here for API convenience. /// /// Will be called before any signatures are applied. - fn on_accept(&mut self, channel_points: &ChannelPublicKeys, remote_to_self_delay: u16, local_to_self_delay: u16); + fn on_accept(&mut self, channel_points: &ChannelPublicKeys, counterparty_to_self_delay: u16, local_to_self_delay: u16); } /// A trait to describe an object which can get user secrets and key material. @@ -360,7 +360,7 @@ struct AcceptedChannelData { /// transactions, ie the amount of time that we have to wait to recover our funds if we /// broadcast a transaction. You'll likely want to pass this to the /// ln::chan_utils::build*_transaction functions when signing local transactions. - remote_to_self_delay: u16, + counterparty_to_self_delay: u16, /// The to_self_delay value specified by us and applied on transactions broadcastable /// by our counterparty, ie the amount of time that they have to wait to recover their funds /// if they broadcast a transaction. @@ -384,7 +384,7 @@ pub struct InMemoryChannelKeys { pub commitment_seed: [u8; 32], /// Local public keys and basepoints pub(crate) local_channel_pubkeys: ChannelPublicKeys, - /// Remote public keys and remote/local to_self_delay, populated on channel acceptance + /// Remote public keys and counterparty/local to_self_delay, populated on channel acceptance accepted_channel_data: Option, /// The total value of this channel channel_value_satoshis: u64, @@ -447,7 +447,7 @@ impl InMemoryChannelKeys { /// broadcast a transaction. You'll likely want to pass this to the /// ln::chan_utils::build*_transaction functions when signing local transactions. /// Will panic if on_accept wasn't called. - pub fn remote_to_self_delay(&self) -> u16 { self.accepted_channel_data.as_ref().unwrap().remote_to_self_delay } + pub fn counterparty_to_self_delay(&self) -> u16 { self.accepted_channel_data.as_ref().unwrap().counterparty_to_self_delay } /// The to_self_delay value specified by us and applied on transactions broadcastable /// by our counterparty, ie the amount of time that they have to wait to recover their funds @@ -485,7 +485,7 @@ impl ChannelKeys for InMemoryChannelKeys { let mut htlc_sigs = Vec::with_capacity(htlcs.len()); for ref htlc in htlcs { if let Some(_) = htlc.transaction_output_index { - let htlc_tx = chan_utils::build_htlc_transaction(&commitment_txid, feerate_per_kw, accepted_data.local_to_self_delay, htlc, &keys.a_delayed_payment_key, &keys.revocation_key); + let htlc_tx = chan_utils::build_htlc_transaction(&commitment_txid, feerate_per_kw, accepted_data.local_to_self_delay, htlc, &keys.delayed_payment_key, &keys.revocation_key); let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &keys); let htlc_sighash = hash_to_message!(&bip143::SigHashCache::new(&htlc_tx).signature_hash(0, &htlc_redeemscript, htlc.amount_msat / 1000, SigHashType::All)[..]); let our_htlc_key = match chan_utils::derive_private_key(&secp_ctx, &keys.per_commitment_point, &self.htlc_base_key) { @@ -517,7 +517,7 @@ impl ChannelKeys for InMemoryChannelKeys { } fn sign_local_commitment_htlc_transactions(&self, local_commitment_tx: &LocalCommitmentTransaction, secp_ctx: &Secp256k1) -> Result>, ()> { - let local_csv = self.accepted_channel_data.as_ref().unwrap().remote_to_self_delay; + let local_csv = self.accepted_channel_data.as_ref().unwrap().counterparty_to_self_delay; local_commitment_tx.get_htlc_sigs(&self.htlc_base_key, local_csv, secp_ctx) } @@ -532,21 +532,21 @@ impl ChannelKeys for InMemoryChannelKeys { Err(_) => return Err(()) }; let witness_script = if let &Some(ref htlc) = htlc { - let remote_htlcpubkey = match chan_utils::derive_public_key(&secp_ctx, &per_commitment_point, &self.remote_pubkeys().htlc_basepoint) { - Ok(remote_htlcpubkey) => remote_htlcpubkey, + let counterparty_htlcpubkey = match chan_utils::derive_public_key(&secp_ctx, &per_commitment_point, &self.remote_pubkeys().htlc_basepoint) { + Ok(counterparty_htlcpubkey) => counterparty_htlcpubkey, Err(_) => return Err(()) }; let local_htlcpubkey = match chan_utils::derive_public_key(&secp_ctx, &per_commitment_point, &self.pubkeys().htlc_basepoint) { Ok(local_htlcpubkey) => local_htlcpubkey, Err(_) => return Err(()) }; - chan_utils::get_htlc_redeemscript_with_explicit_keys(&htlc, &remote_htlcpubkey, &local_htlcpubkey, &revocation_pubkey) + chan_utils::get_htlc_redeemscript_with_explicit_keys(&htlc, &counterparty_htlcpubkey, &local_htlcpubkey, &revocation_pubkey) } else { - let remote_delayedpubkey = match chan_utils::derive_public_key(&secp_ctx, &per_commitment_point, &self.remote_pubkeys().delayed_payment_basepoint) { - Ok(remote_delayedpubkey) => remote_delayedpubkey, + let counterparty_delayedpubkey = match chan_utils::derive_public_key(&secp_ctx, &per_commitment_point, &self.remote_pubkeys().delayed_payment_basepoint) { + Ok(counterparty_delayedpubkey) => counterparty_delayedpubkey, Err(_) => return Err(()) }; - chan_utils::get_revokeable_redeemscript(&revocation_pubkey, self.local_to_self_delay(), &remote_delayedpubkey) + chan_utils::get_revokeable_redeemscript(&revocation_pubkey, self.local_to_self_delay(), &counterparty_delayedpubkey) }; let mut sighash_parts = bip143::SigHashCache::new(justice_tx); let sighash = hash_to_message!(&sighash_parts.signature_hash(input, &witness_script, amount, SigHashType::All)[..]); @@ -556,9 +556,9 @@ impl ChannelKeys for InMemoryChannelKeys { fn sign_remote_htlc_transaction(&self, htlc_tx: &Transaction, input: usize, amount: u64, per_commitment_point: &PublicKey, htlc: &HTLCOutputInCommitment, secp_ctx: &Secp256k1) -> Result { if let Ok(htlc_key) = chan_utils::derive_private_key(&secp_ctx, &per_commitment_point, &self.htlc_base_key) { let witness_script = if let Ok(revocation_pubkey) = chan_utils::derive_public_revocation_key(&secp_ctx, &per_commitment_point, &self.pubkeys().revocation_basepoint) { - if let Ok(remote_htlcpubkey) = chan_utils::derive_public_key(&secp_ctx, &per_commitment_point, &self.remote_pubkeys().htlc_basepoint) { - if let Ok(local_htlcpubkey) = chan_utils::derive_public_key(&secp_ctx, &per_commitment_point, &self.pubkeys().htlc_basepoint) { - chan_utils::get_htlc_redeemscript_with_explicit_keys(&htlc, &remote_htlcpubkey, &local_htlcpubkey, &revocation_pubkey) + if let Ok(counterparty_htlcpubkey) = chan_utils::derive_public_key(&secp_ctx, &per_commitment_point, &self.remote_pubkeys().htlc_basepoint) { + if let Ok(htlcpubkey) = chan_utils::derive_public_key(&secp_ctx, &per_commitment_point, &self.pubkeys().htlc_basepoint) { + chan_utils::get_htlc_redeemscript_with_explicit_keys(&htlc, &counterparty_htlcpubkey, &htlcpubkey, &revocation_pubkey) } else { return Err(()) } } else { return Err(()) } } else { return Err(()) }; @@ -588,18 +588,18 @@ impl ChannelKeys for InMemoryChannelKeys { Ok(secp_ctx.sign(&msghash, &self.funding_key)) } - fn on_accept(&mut self, channel_pubkeys: &ChannelPublicKeys, remote_to_self_delay: u16, local_to_self_delay: u16) { + fn on_accept(&mut self, channel_pubkeys: &ChannelPublicKeys, counterparty_to_self_delay: u16, local_to_self_delay: u16) { assert!(self.accepted_channel_data.is_none(), "Already accepted"); self.accepted_channel_data = Some(AcceptedChannelData { remote_channel_pubkeys: channel_pubkeys.clone(), - remote_to_self_delay, + counterparty_to_self_delay, local_to_self_delay, }); } } impl_writeable!(AcceptedChannelData, 0, - { remote_channel_pubkeys, remote_to_self_delay, local_to_self_delay }); + { remote_channel_pubkeys, counterparty_to_self_delay, local_to_self_delay }); impl Writeable for InMemoryChannelKeys { fn write(&self, writer: &mut W) -> Result<(), Error> { diff --git a/lightning/src/ln/chan_utils.rs b/lightning/src/ln/chan_utils.rs index beec83839..d57f987d0 100644 --- a/lightning/src/ln/chan_utils.rs +++ b/lightning/src/ln/chan_utils.rs @@ -238,12 +238,16 @@ pub fn derive_private_revocation_key(secp_ctx: &Secp256k1 Sha256::from_engine(sha).into_inner() }; - let mut part_a = revocation_base_secret.clone(); - part_a.mul_assign(&rev_append_commit_hash_key)?; - let mut part_b = per_commitment_secret.clone(); - part_b.mul_assign(&commit_append_rev_hash_key)?; - part_a.add_assign(&part_b[..])?; - Ok(part_a) + // Only the transaction broadcaster owns a valid witness to propagate + // a revoked commitment transaction, thus per_commitment_secret always + // come from broadcaster and revocation_base_secret always come + // from countersignatory of the transaction. + let mut countersignatory_contrib = revocation_base_secret.clone(); + countersignatory_contrib.mul_assign(&rev_append_commit_hash_key)?; + let mut broadcaster_contrib = per_commitment_secret.clone(); + broadcaster_contrib.mul_assign(&commit_append_rev_hash_key)?; + countersignatory_contrib.add_assign(&broadcaster_contrib[..])?; + Ok(countersignatory_contrib) } /// Derives a per-commitment-transaction revocation public key from its constituent parts. This is @@ -268,36 +272,45 @@ pub fn derive_public_revocation_key(secp_ctx: &Secp2 Sha256::from_engine(sha).into_inner() }; - let mut part_a = revocation_base_point.clone(); - part_a.mul_assign(&secp_ctx, &rev_append_commit_hash_key)?; - let mut part_b = per_commitment_point.clone(); - part_b.mul_assign(&secp_ctx, &commit_append_rev_hash_key)?; - part_a.combine(&part_b) + // Only the transaction broadcaster owns a valid witness to propagate + // a revoked commitment transaction, thus per_commitment_point always + // come from broadcaster and revocation_base_point always come + // from countersignatory of the transaction. + let mut countersignatory_contrib = revocation_base_point.clone(); + countersignatory_contrib.mul_assign(&secp_ctx, &rev_append_commit_hash_key)?; + let mut broadcaster_contrib = per_commitment_point.clone(); + broadcaster_contrib.mul_assign(&secp_ctx, &commit_append_rev_hash_key)?; + countersignatory_contrib.combine(&broadcaster_contrib) } /// The set of public keys which are used in the creation of one commitment transaction. /// These are derived from the channel base keys and per-commitment data. /// +/// A broadcaster key is provided from potential broadcaster of the computed transaction. +/// A countersignatory key is coming from a protocol participant unable to broadcast the +/// transaction. +/// /// These keys are assumed to be good, either because the code derived them from /// channel basepoints via the new function, or they were obtained via /// PreCalculatedTxCreationKeys.trust_key_derivation because we trusted the source of the /// pre-calculated keys. #[derive(PartialEq, Clone)] pub struct TxCreationKeys { - /// The per-commitment public key which was used to derive the other keys. + /// The broadcaster's per-commitment public key which was used to derive the other keys. pub per_commitment_point: PublicKey, - /// The revocation key which is used to allow the owner of the commitment transaction to - /// provide their counterparty the ability to punish them if they broadcast an old state. + /// The broadcaster's revocation key which is used to allow the broadcaster of the commitment + /// transaction to provide their counterparty the ability to punish them if they broadcast + /// an old state. pub revocation_key: PublicKey, - /// A's HTLC Key - pub a_htlc_key: PublicKey, - /// B's HTLC Key - pub b_htlc_key: PublicKey, - /// A's Payment Key (which isn't allowed to be spent from for some delay) - pub a_delayed_payment_key: PublicKey, + /// Broadcaster's HTLC Key + pub broadcaster_htlc_key: PublicKey, + /// Countersignatory's HTLC Key + pub countersignatory_htlc_key: PublicKey, + /// Broadcaster's Payment Key (which isn't allowed to be spent from for some delay) + pub delayed_payment_key: PublicKey, } impl_writeable!(TxCreationKeys, 33*6, - { per_commitment_point, revocation_key, a_htlc_key, b_htlc_key, a_delayed_payment_key }); + { per_commitment_point, revocation_key, broadcaster_htlc_key, countersignatory_htlc_key, delayed_payment_key }); /// The per-commitment point and a set of pre-calculated public keys used for transaction creation /// in the signer. @@ -358,13 +371,13 @@ impl_writeable!(ChannelPublicKeys, 33*5, { impl TxCreationKeys { /// Create a new TxCreationKeys from channel base points and the per-commitment point - pub fn derive_new(secp_ctx: &Secp256k1, per_commitment_point: &PublicKey, a_delayed_payment_base: &PublicKey, a_htlc_base: &PublicKey, b_revocation_base: &PublicKey, b_htlc_base: &PublicKey) -> Result { + pub fn derive_new(secp_ctx: &Secp256k1, per_commitment_point: &PublicKey, broadcaster_delayed_payment_base: &PublicKey, broadcaster_htlc_base: &PublicKey, countersignatory_revocation_base: &PublicKey, countersignatory_htlc_base: &PublicKey) -> Result { Ok(TxCreationKeys { per_commitment_point: per_commitment_point.clone(), - revocation_key: derive_public_revocation_key(&secp_ctx, &per_commitment_point, &b_revocation_base)?, - a_htlc_key: derive_public_key(&secp_ctx, &per_commitment_point, &a_htlc_base)?, - b_htlc_key: derive_public_key(&secp_ctx, &per_commitment_point, &b_htlc_base)?, - a_delayed_payment_key: derive_public_key(&secp_ctx, &per_commitment_point, &a_delayed_payment_base)?, + revocation_key: derive_public_revocation_key(&secp_ctx, &per_commitment_point, &countersignatory_revocation_base)?, + broadcaster_htlc_key: derive_public_key(&secp_ctx, &per_commitment_point, &broadcaster_htlc_base)?, + countersignatory_htlc_key: derive_public_key(&secp_ctx, &per_commitment_point, &countersignatory_htlc_base)?, + delayed_payment_key: derive_public_key(&secp_ctx, &per_commitment_point, &broadcaster_delayed_payment_base)?, }) } } @@ -415,7 +428,7 @@ impl_writeable!(HTLCOutputInCommitment, 1 + 8 + 4 + 32 + 5, { }); #[inline] -pub(crate) fn get_htlc_redeemscript_with_explicit_keys(htlc: &HTLCOutputInCommitment, a_htlc_key: &PublicKey, b_htlc_key: &PublicKey, revocation_key: &PublicKey) -> Script { +pub(crate) fn get_htlc_redeemscript_with_explicit_keys(htlc: &HTLCOutputInCommitment, broadcaster_htlc_key: &PublicKey, countersignatory_htlc_key: &PublicKey, revocation_key: &PublicKey) -> Script { let payment_hash160 = Ripemd160::hash(&htlc.payment_hash.0[..]).into_inner(); if htlc.offered { Builder::new().push_opcode(opcodes::all::OP_DUP) @@ -425,7 +438,7 @@ pub(crate) fn get_htlc_redeemscript_with_explicit_keys(htlc: &HTLCOutputInCommit .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_slice(&countersignatory_htlc_key.serialize()[..]) .push_opcode(opcodes::all::OP_SWAP) .push_opcode(opcodes::all::OP_SIZE) .push_int(32) @@ -434,7 +447,7 @@ pub(crate) fn get_htlc_redeemscript_with_explicit_keys(htlc: &HTLCOutputInCommit .push_opcode(opcodes::all::OP_DROP) .push_int(2) .push_opcode(opcodes::all::OP_SWAP) - .push_slice(&a_htlc_key.serialize()[..]) + .push_slice(&broadcaster_htlc_key.serialize()[..]) .push_int(2) .push_opcode(opcodes::all::OP_CHECKMULTISIG) .push_opcode(opcodes::all::OP_ELSE) @@ -453,7 +466,7 @@ pub(crate) fn get_htlc_redeemscript_with_explicit_keys(htlc: &HTLCOutputInCommit .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_slice(&countersignatory_htlc_key.serialize()[..]) .push_opcode(opcodes::all::OP_SWAP) .push_opcode(opcodes::all::OP_SIZE) .push_int(32) @@ -464,7 +477,7 @@ pub(crate) fn get_htlc_redeemscript_with_explicit_keys(htlc: &HTLCOutputInCommit .push_opcode(opcodes::all::OP_EQUALVERIFY) .push_int(2) .push_opcode(opcodes::all::OP_SWAP) - .push_slice(&a_htlc_key.serialize()[..]) + .push_slice(&broadcaster_htlc_key.serialize()[..]) .push_int(2) .push_opcode(opcodes::all::OP_CHECKMULTISIG) .push_opcode(opcodes::all::OP_ELSE) @@ -479,31 +492,31 @@ pub(crate) fn get_htlc_redeemscript_with_explicit_keys(htlc: &HTLCOutputInCommit } } -/// note here that 'a_revocation_key' is generated using b_revocation_basepoint and a's +/// note here that 'revocation_key' is generated using countersignatory_revocation_basepoint and broadcaster's /// commitment secret. 'htlc' does *not* need to have its previous_output_index filled. #[inline] pub fn get_htlc_redeemscript(htlc: &HTLCOutputInCommitment, keys: &TxCreationKeys) -> Script { - get_htlc_redeemscript_with_explicit_keys(htlc, &keys.a_htlc_key, &keys.b_htlc_key, &keys.revocation_key) + get_htlc_redeemscript_with_explicit_keys(htlc, &keys.broadcaster_htlc_key, &keys.countersignatory_htlc_key, &keys.revocation_key) } /// Gets the redeemscript for a funding output from the two funding public keys. /// Note that the order of funding public keys does not matter. -pub fn make_funding_redeemscript(a: &PublicKey, b: &PublicKey) -> Script { - let our_funding_key = a.serialize(); - let their_funding_key = b.serialize(); +pub fn make_funding_redeemscript(broadcaster: &PublicKey, countersignatory: &PublicKey) -> Script { + let broadcaster_funding_key = broadcaster.serialize(); + let countersignatory_funding_key = countersignatory.serialize(); let builder = Builder::new().push_opcode(opcodes::all::OP_PUSHNUM_2); - if our_funding_key[..] < their_funding_key[..] { - builder.push_slice(&our_funding_key) - .push_slice(&their_funding_key) + if broadcaster_funding_key[..] < countersignatory_funding_key[..] { + builder.push_slice(&broadcaster_funding_key) + .push_slice(&countersignatory_funding_key) } else { - builder.push_slice(&their_funding_key) - .push_slice(&our_funding_key) + builder.push_slice(&countersignatory_funding_key) + .push_slice(&broadcaster_funding_key) }.push_opcode(opcodes::all::OP_PUSHNUM_2).push_opcode(opcodes::all::OP_CHECKMULTISIG).into_script() } /// panics if htlc.transaction_output_index.is_none()! -pub fn build_htlc_transaction(prev_hash: &Txid, feerate_per_kw: u32, to_self_delay: u16, htlc: &HTLCOutputInCommitment, a_delayed_payment_key: &PublicKey, revocation_key: &PublicKey) -> Transaction { +pub fn build_htlc_transaction(prev_hash: &Txid, feerate_per_kw: u32, to_self_delay: u16, htlc: &HTLCOutputInCommitment, delayed_payment_key: &PublicKey, revocation_key: &PublicKey) -> Transaction { let mut txins: Vec = Vec::new(); txins.push(TxIn { previous_output: OutPoint { @@ -523,7 +536,7 @@ pub fn build_htlc_transaction(prev_hash: &Txid, feerate_per_kw: u32, to_self_del let mut txouts: Vec = Vec::new(); txouts.push(TxOut { - script_pubkey: get_revokeable_redeemscript(revocation_key, to_self_delay, a_delayed_payment_key).to_v0_p2wsh(), + script_pubkey: get_revokeable_redeemscript(revocation_key, to_self_delay, 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) }); @@ -590,9 +603,9 @@ impl LocalCommitmentTransaction { local_keys: TxCreationKeys { per_commitment_point: dummy_key.clone(), revocation_key: dummy_key.clone(), - a_htlc_key: dummy_key.clone(), - b_htlc_key: dummy_key.clone(), - a_delayed_payment_key: dummy_key.clone(), + broadcaster_htlc_key: dummy_key.clone(), + countersignatory_htlc_key: dummy_key.clone(), + delayed_payment_key: dummy_key.clone(), }, feerate_per_kw: 0, per_htlc: Vec::new() @@ -688,9 +701,9 @@ impl LocalCommitmentTransaction { for this_htlc in self.per_htlc.iter() { if this_htlc.0.transaction_output_index.is_some() { - let htlc_tx = build_htlc_transaction(&txid, self.feerate_per_kw, local_csv, &this_htlc.0, &self.local_keys.a_delayed_payment_key, &self.local_keys.revocation_key); + let htlc_tx = build_htlc_transaction(&txid, self.feerate_per_kw, local_csv, &this_htlc.0, &self.local_keys.delayed_payment_key, &self.local_keys.revocation_key); - let htlc_redeemscript = get_htlc_redeemscript_with_explicit_keys(&this_htlc.0, &self.local_keys.a_htlc_key, &self.local_keys.b_htlc_key, &self.local_keys.revocation_key); + let htlc_redeemscript = get_htlc_redeemscript_with_explicit_keys(&this_htlc.0, &self.local_keys.broadcaster_htlc_key, &self.local_keys.countersignatory_htlc_key, &self.local_keys.revocation_key); let sighash = hash_to_message!(&bip143::SigHashCache::new(&htlc_tx).signature_hash(0, &htlc_redeemscript, this_htlc.0.amount_msat / 1000, SigHashType::All)[..]); ret.push(Some(secp_ctx.sign(&sighash, &our_htlc_key))); @@ -711,12 +724,12 @@ impl LocalCommitmentTransaction { // Further, we should never be provided the preimage for an HTLC-Timeout transaction. if this_htlc.0.offered && preimage.is_some() { unreachable!(); } - let mut htlc_tx = build_htlc_transaction(&txid, self.feerate_per_kw, local_csv, &this_htlc.0, &self.local_keys.a_delayed_payment_key, &self.local_keys.revocation_key); + let mut htlc_tx = build_htlc_transaction(&txid, self.feerate_per_kw, local_csv, &this_htlc.0, &self.local_keys.delayed_payment_key, &self.local_keys.revocation_key); // Channel should have checked that we have a remote signature for this HTLC at // creation, and we should have a sensible htlc transaction: assert!(this_htlc.1.is_some()); - let htlc_redeemscript = get_htlc_redeemscript_with_explicit_keys(&this_htlc.0, &self.local_keys.a_htlc_key, &self.local_keys.b_htlc_key, &self.local_keys.revocation_key); + let htlc_redeemscript = get_htlc_redeemscript_with_explicit_keys(&this_htlc.0, &self.local_keys.broadcaster_htlc_key, &self.local_keys.countersignatory_htlc_key, &self.local_keys.revocation_key); // First push the multisig dummy, note that due to BIP147 (NULLDUMMY) it must be a zero-length element. htlc_tx.input[0].witness.push(Vec::new()); diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index 9a4fd1ada..3dee6ee4d 100644 --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@ -617,9 +617,9 @@ impl Channel { } Channel::::check_remote_fee(fee_estimator, msg.feerate_per_kw)?; - let max_to_self_delay = u16::min(config.peer_channel_config_limits.their_to_self_delay, MAX_LOCAL_BREAKDOWN_TIMEOUT); - if msg.to_self_delay > max_to_self_delay { - return Err(ChannelError::Close(format!("They wanted our payments to be delayed by a needlessly long period. Upper limit: {}. Actual: {}", max_to_self_delay, msg.to_self_delay))); + let max_counterparty_selected_contest_delay = u16::min(config.peer_channel_config_limits.their_to_self_delay, MAX_LOCAL_BREAKDOWN_TIMEOUT); + if msg.to_self_delay > max_counterparty_selected_contest_delay { + return Err(ChannelError::Close(format!("They wanted our payments to be delayed by a needlessly long period. Upper limit: {}. Actual: {}", max_counterparty_selected_contest_delay, msg.to_self_delay))); } if msg.max_accepted_htlcs < 1 { return Err(ChannelError::Close("0 max_accepted_htlcs makes for a useless channel".to_owned())); @@ -990,7 +990,7 @@ impl Channel { txouts.push((TxOut { script_pubkey: chan_utils::get_revokeable_redeemscript(&keys.revocation_key, if local { self.their_to_self_delay } else { self.our_to_self_delay }, - &keys.a_delayed_payment_key).to_v0_p2wsh(), + &keys.delayed_payment_key).to_v0_p2wsh(), value: value_to_a as u64 }, None)); } @@ -1117,7 +1117,7 @@ impl Channel { /// 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) + /// The result is a transaction which we can revoke broadcastership 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 { let per_commitment_point = self.local_keys.get_per_commitment_point(commitment_number, &self.secp_ctx); @@ -1153,7 +1153,7 @@ impl Channel { /// @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: &Txid, htlc: &HTLCOutputInCommitment, local: bool, keys: &TxCreationKeys, feerate_per_kw: u32) -> Transaction { - chan_utils::build_htlc_transaction(prev_hash, feerate_per_kw, if local { self.their_to_self_delay } else { self.our_to_self_delay }, htlc, &keys.a_delayed_payment_key, &keys.revocation_key) + chan_utils::build_htlc_transaction(prev_hash, feerate_per_kw, if local { self.their_to_self_delay } else { self.our_to_self_delay }, htlc, &keys.delayed_payment_key, &keys.revocation_key) } /// Per HTLC, only one get_update_fail_htlc or get_update_fulfill_htlc call may be made. @@ -2011,8 +2011,8 @@ impl Channel { let htlc_tx = self.build_htlc_transaction(&local_commitment_txid, &htlc, true, &local_keys, feerate_per_kw); let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &local_keys); let htlc_sighash = hash_to_message!(&bip143::SigHashCache::new(&htlc_tx).signature_hash(0, &htlc_redeemscript, htlc.amount_msat / 1000, SigHashType::All)[..]); - log_trace!(logger, "Checking HTLC tx signature {} by key {} against tx {} (sighash {}) with redeemscript {}", log_bytes!(msg.htlc_signatures[idx].serialize_compact()[..]), log_bytes!(local_keys.b_htlc_key.serialize()), encode::serialize_hex(&htlc_tx), log_bytes!(htlc_sighash[..]), encode::serialize_hex(&htlc_redeemscript)); - if let Err(_) = self.secp_ctx.verify(&htlc_sighash, &msg.htlc_signatures[idx], &local_keys.b_htlc_key) { + log_trace!(logger, "Checking HTLC tx signature {} by key {} against tx {} (sighash {}) with redeemscript {}", log_bytes!(msg.htlc_signatures[idx].serialize_compact()[..]), log_bytes!(local_keys.countersignatory_htlc_key.serialize()), encode::serialize_hex(&htlc_tx), log_bytes!(htlc_sighash[..]), encode::serialize_hex(&htlc_redeemscript)); + if let Err(_) = self.secp_ctx.verify(&htlc_sighash, &msg.htlc_signatures[idx], &local_keys.countersignatory_htlc_key) { return Err((None, ChannelError::Close("Invalid HTLC tx signature from peer".to_owned()))); } htlcs_without_source.push((htlc.clone(), Some(msg.htlc_signatures[idx]))); @@ -3884,9 +3884,9 @@ impl Channel { for (ref htlc_sig, ref htlc) in htlc_signatures.iter().zip(htlcs) { log_trace!(logger, "Signed remote HTLC tx {} with redeemscript {} with pubkey {} -> {}", - encode::serialize_hex(&chan_utils::build_htlc_transaction(&remote_commitment_tx.0.txid(), feerate_per_kw, self.our_to_self_delay, htlc, &remote_keys.a_delayed_payment_key, &remote_keys.revocation_key)), + encode::serialize_hex(&chan_utils::build_htlc_transaction(&remote_commitment_tx.0.txid(), feerate_per_kw, self.our_to_self_delay, htlc, &remote_keys.delayed_payment_key, &remote_keys.revocation_key)), encode::serialize_hex(&chan_utils::get_htlc_redeemscript(&htlc, remote_keys)), - log_bytes!(remote_keys.a_htlc_key.serialize()), + log_bytes!(remote_keys.broadcaster_htlc_key.serialize()), log_bytes!(htlc_sig.serialize_compact()[..])); } } @@ -4719,7 +4719,7 @@ mod tests { let htlc_tx = chan.build_htlc_transaction(&unsigned_tx.0.txid(), &htlc, true, &keys, chan.feerate_per_kw); let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &keys); let htlc_sighash = Message::from_slice(&bip143::SigHashCache::new(&htlc_tx).signature_hash(0, &htlc_redeemscript, htlc.amount_msat / 1000, SigHashType::All)[..]).unwrap(); - secp_ctx.verify(&htlc_sighash, &remote_signature, &keys.b_htlc_key).unwrap(); + secp_ctx.verify(&htlc_sighash, &remote_signature, &keys.countersignatory_htlc_key).unwrap(); let mut preimage: Option = None; if !htlc.offered { diff --git a/lightning/src/ln/channelmonitor.rs b/lightning/src/ln/channelmonitor.rs index 363696443..3b1318052 100644 --- a/lightning/src/ln/channelmonitor.rs +++ b/lightning/src/ln/channelmonitor.rs @@ -1160,9 +1160,9 @@ impl ChannelMonitor { let local_commitment_tx = LocalSignedTx { txid: initial_local_commitment_tx.txid(), revocation_key: initial_local_commitment_tx.local_keys.revocation_key, - a_htlc_key: initial_local_commitment_tx.local_keys.a_htlc_key, - b_htlc_key: initial_local_commitment_tx.local_keys.b_htlc_key, - delayed_payment_key: initial_local_commitment_tx.local_keys.a_delayed_payment_key, + a_htlc_key: initial_local_commitment_tx.local_keys.broadcaster_htlc_key, + b_htlc_key: initial_local_commitment_tx.local_keys.countersignatory_htlc_key, + delayed_payment_key: initial_local_commitment_tx.local_keys.delayed_payment_key, per_commitment_point: initial_local_commitment_tx.local_keys.per_commitment_point, feerate_per_kw: initial_local_commitment_tx.feerate_per_kw, htlc_outputs: Vec::new(), // There are never any HTLCs in the initial commitment transactions @@ -1336,9 +1336,9 @@ impl ChannelMonitor { let mut new_local_commitment_tx = LocalSignedTx { txid, revocation_key: commitment_tx.local_keys.revocation_key, - a_htlc_key: commitment_tx.local_keys.a_htlc_key, - b_htlc_key: commitment_tx.local_keys.b_htlc_key, - delayed_payment_key: commitment_tx.local_keys.a_delayed_payment_key, + a_htlc_key: commitment_tx.local_keys.broadcaster_htlc_key, + b_htlc_key: commitment_tx.local_keys.countersignatory_htlc_key, + delayed_payment_key: commitment_tx.local_keys.delayed_payment_key, per_commitment_point: commitment_tx.local_keys.per_commitment_point, feerate_per_kw: commitment_tx.feerate_per_kw, htlc_outputs: htlc_outputs, diff --git a/lightning/src/ln/functional_tests.rs b/lightning/src/ln/functional_tests.rs index 0bf0e9efe..e60520ffc 100644 --- a/lightning/src/ln/functional_tests.rs +++ b/lightning/src/ln/functional_tests.rs @@ -1652,7 +1652,7 @@ fn test_fee_spike_violation_fails_htlc() { let local_commit_tx_output = TxOut { script_pubkey: chan_utils::get_revokeable_redeemscript(&commit_tx_keys.revocation_key, BREAKDOWN_TIMEOUT, - &commit_tx_keys.a_delayed_payment_key).to_v0_p2wsh(), + &commit_tx_keys.delayed_payment_key).to_v0_p2wsh(), value: 95000, }; diff --git a/lightning/src/ln/onchaintx.rs b/lightning/src/ln/onchaintx.rs index 37c7f3964..1292f8e43 100644 --- a/lightning/src/ln/onchaintx.rs +++ b/lightning/src/ln/onchaintx.rs @@ -586,9 +586,9 @@ impl OnchainTxHandler { if let Ok(chan_keys) = TxCreationKeys::derive_new(&self.secp_ctx, &per_commitment_point, remote_delayed_payment_base_key, remote_htlc_base_key, &self.key_storage.pubkeys().revocation_basepoint, &self.key_storage.pubkeys().htlc_basepoint) { let witness_script = if let Some(ref htlc) = *htlc { - chan_utils::get_htlc_redeemscript_with_explicit_keys(&htlc, &chan_keys.a_htlc_key, &chan_keys.b_htlc_key, &chan_keys.revocation_key) + chan_utils::get_htlc_redeemscript_with_explicit_keys(&htlc, &chan_keys.broadcaster_htlc_key, &chan_keys.countersignatory_htlc_key, &chan_keys.revocation_key) } else { - chan_utils::get_revokeable_redeemscript(&chan_keys.revocation_key, *on_remote_tx_csv, &chan_keys.a_delayed_payment_key) + chan_utils::get_revokeable_redeemscript(&chan_keys.revocation_key, *on_remote_tx_csv, &chan_keys.delayed_payment_key) }; if let Ok(sig) = self.key_storage.sign_justice_transaction(&bumped_tx, i, *amount, &per_commitment_key, htlc, &self.secp_ctx) { @@ -608,7 +608,7 @@ impl OnchainTxHandler { }, &InputMaterial::RemoteHTLC { ref per_commitment_point, ref remote_delayed_payment_base_key, ref remote_htlc_base_key, ref preimage, ref htlc } => { if let Ok(chan_keys) = TxCreationKeys::derive_new(&self.secp_ctx, &per_commitment_point, remote_delayed_payment_base_key, remote_htlc_base_key, &self.key_storage.pubkeys().revocation_basepoint, &self.key_storage.pubkeys().htlc_basepoint) { - let witness_script = chan_utils::get_htlc_redeemscript_with_explicit_keys(&htlc, &chan_keys.a_htlc_key, &chan_keys.b_htlc_key, &chan_keys.revocation_key); + let witness_script = chan_utils::get_htlc_redeemscript_with_explicit_keys(&htlc, &chan_keys.broadcaster_htlc_key, &chan_keys.countersignatory_htlc_key, &chan_keys.revocation_key); if !preimage.is_some() { bumped_tx.lock_time = htlc.cltv_expiry }; // Right now we don't aggregate time-locked transaction, if we do we should set lock_time before to avoid breaking hash computation if let Ok(sig) = self.key_storage.sign_remote_htlc_transaction(&bumped_tx, i, &htlc.amount_msat / 1000, &per_commitment_point, htlc, &self.secp_ctx) { diff --git a/lightning/src/util/enforcing_trait_impls.rs b/lightning/src/util/enforcing_trait_impls.rs index 557f06b5d..b001fb1a6 100644 --- a/lightning/src/util/enforcing_trait_impls.rs +++ b/lightning/src/util/enforcing_trait_impls.rs @@ -100,16 +100,16 @@ impl ChannelKeys for EnforcingChannelKeys { fn sign_local_commitment_htlc_transactions(&self, local_commitment_tx: &LocalCommitmentTransaction, secp_ctx: &Secp256k1) -> Result>, ()> { let commitment_txid = local_commitment_tx.txid(); - let local_csv = self.inner.remote_to_self_delay(); + let local_csv = self.inner.counterparty_to_self_delay(); for this_htlc in local_commitment_tx.per_htlc.iter() { if this_htlc.0.transaction_output_index.is_some() { - let htlc_tx = chan_utils::build_htlc_transaction(&commitment_txid, local_commitment_tx.feerate_per_kw, local_csv, &this_htlc.0, &local_commitment_tx.local_keys.a_delayed_payment_key, &local_commitment_tx.local_keys.revocation_key); + let htlc_tx = chan_utils::build_htlc_transaction(&commitment_txid, local_commitment_tx.feerate_per_kw, local_csv, &this_htlc.0, &local_commitment_tx.local_keys.delayed_payment_key, &local_commitment_tx.local_keys.revocation_key); let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&this_htlc.0, &local_commitment_tx.local_keys); let sighash = hash_to_message!(&bip143::SigHashCache::new(&htlc_tx).signature_hash(0, &htlc_redeemscript, this_htlc.0.amount_msat / 1000, SigHashType::All)[..]); - secp_ctx.verify(&sighash, this_htlc.1.as_ref().unwrap(), &local_commitment_tx.local_keys.b_htlc_key).unwrap(); + secp_ctx.verify(&sighash, this_htlc.1.as_ref().unwrap(), &local_commitment_tx.local_keys.countersignatory_htlc_key).unwrap(); } } -- 2.39.5