X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fchan_utils.rs;h=219f155a5c4def3248cd180d81a18586dc6d943e;hb=605d30eb034a879db4d5719730c88074b9347026;hp=df0378938b42eeb0b1ff0fbd1413f6f140617a12;hpb=cd0d19c005ee4fa11de93a2bca621eda6b81ce95;p=rust-lightning diff --git a/lightning/src/ln/chan_utils.rs b/lightning/src/ln/chan_utils.rs index df037893..219f155a 100644 --- a/lightning/src/ln/chan_utils.rs +++ b/lightning/src/ln/chan_utils.rs @@ -14,40 +14,48 @@ use bitcoin::blockdata::script::{Script,Builder}; use bitcoin::blockdata::opcodes; use bitcoin::blockdata::transaction::{TxIn,TxOut,OutPoint,Transaction, EcdsaSighashType}; use bitcoin::util::sighash; +use bitcoin::util::address::Payload; use bitcoin::hashes::{Hash, HashEngine}; use bitcoin::hashes::sha256::Hash as Sha256; use bitcoin::hashes::ripemd160::Hash as Ripemd160; use bitcoin::hash_types::{Txid, PubkeyHash}; -use ln::{PaymentHash, PaymentPreimage}; -use ln::msgs::DecodeError; -use util::ser::{Readable, Writeable, Writer}; -use util::{byte_utils, transaction_utils}; +use crate::ln::{PaymentHash, PaymentPreimage}; +use crate::ln::msgs::DecodeError; +use crate::util::ser::{Readable, Writeable, Writer}; +use crate::util::{byte_utils, transaction_utils}; -use bitcoin::hash_types::WPubkeyHash; use bitcoin::secp256k1::{SecretKey, PublicKey, Scalar}; use bitcoin::secp256k1::{Secp256k1, ecdsa::Signature, Message}; use bitcoin::secp256k1::Error as SecpError; use bitcoin::{PackedLockTime, secp256k1, Sequence, Witness}; +use bitcoin::PublicKey as BitcoinPublicKey; -use io; -use prelude::*; +use crate::io; +use crate::prelude::*; use core::cmp; -use ln::chan_utils; -use util::transaction_utils::sort_outputs; -use ln::channel::{INITIAL_COMMITMENT_NUMBER, ANCHOR_OUTPUT_VALUE_SATOSHI}; +use crate::ln::chan_utils; +use crate::util::transaction_utils::sort_outputs; +use crate::ln::channel::{INITIAL_COMMITMENT_NUMBER, ANCHOR_OUTPUT_VALUE_SATOSHI}; use core::ops::Deref; -use chain; -use util::crypto::sign; - -pub(crate) const MAX_HTLCS: u16 = 483; -pub(crate) const OFFERED_HTLC_SCRIPT_WEIGHT: usize = 133; -pub(crate) const OFFERED_HTLC_SCRIPT_WEIGHT_ANCHORS: usize = 136; -// The weight of `accepted_htlc_script` can vary in function of its CLTV argument value. We define a -// range that encompasses both its non-anchors and anchors variants. +use crate::chain; +use crate::util::crypto::sign; + +/// Maximum number of one-way in-flight HTLC (protocol-level value). +pub const MAX_HTLCS: u16 = 483; +/// The weight of a BIP141 witnessScript for a BOLT3's "offered HTLC output" on a commitment transaction, non-anchor variant. +pub const OFFERED_HTLC_SCRIPT_WEIGHT: usize = 133; +/// The weight of a BIP141 witnessScript for a BOLT3's "offered HTLC output" on a commitment transaction, anchor variant. +pub const OFFERED_HTLC_SCRIPT_WEIGHT_ANCHORS: usize = 136; + +/// The weight of a BIP141 witnessScript for a BOLT3's "received HTLC output" can vary in function of its CLTV argument value. +/// We define a range that encompasses both its non-anchors and anchors variants. pub(crate) const MIN_ACCEPTED_HTLC_SCRIPT_WEIGHT: usize = 136; -pub(crate) const MAX_ACCEPTED_HTLC_SCRIPT_WEIGHT: usize = 143; +/// The weight of a BIP141 witnessScript for a BOLT3's "received HTLC output" can vary in function of its CLTV argument value. +/// We define a range that encompasses both its non-anchors and anchors variants. +/// This is the maximum post-anchor value. +pub const MAX_ACCEPTED_HTLC_SCRIPT_WEIGHT: usize = 143; /// Gets the weight for an HTLC-Success transaction. #[inline] @@ -65,18 +73,24 @@ pub fn htlc_timeout_tx_weight(opt_anchors: bool) -> u64 { if opt_anchors { HTLC_TIMEOUT_ANCHOR_TX_WEIGHT } else { HTLC_TIMEOUT_TX_WEIGHT } } -#[derive(PartialEq)] -pub(crate) enum HTLCClaim { +/// Describes the type of HTLC claim as determined by analyzing the witness. +#[derive(PartialEq, Eq)] +pub enum HTLCClaim { + /// Claims an offered output on a commitment transaction through the timeout path. OfferedTimeout, + /// Claims an offered output on a commitment transaction through the success path. OfferedPreimage, + /// Claims an accepted output on a commitment transaction through the timeout path. AcceptedTimeout, + /// Claims an accepted output on a commitment transaction through the success path. AcceptedPreimage, + /// Claims an offered/accepted output on a commitment transaction through the revocation path. Revocation, } impl HTLCClaim { /// Check if a given input witness attempts to claim a HTLC. - pub(crate) fn from_witness(witness: &Witness) -> Option { + pub fn from_witness(witness: &Witness) -> Option { debug_assert_eq!(OFFERED_HTLC_SCRIPT_WEIGHT_ANCHORS, MIN_ACCEPTED_HTLC_SCRIPT_WEIGHT); if witness.len() < 2 { return None; @@ -208,6 +222,7 @@ pub struct CounterpartyCommitmentSecrets { old_secrets: [([u8; 32], u64); 49], } +impl Eq for CounterpartyCommitmentSecrets {} impl PartialEq for CounterpartyCommitmentSecrets { fn eq(&self, other: &Self) -> bool { for (&(ref secret, ref idx), &(ref o_secret, ref o_idx)) in self.old_secrets.iter().zip(other.old_secrets.iter()) { @@ -419,7 +434,7 @@ pub fn derive_public_revocation_key(secp_ctx: &Secp2 /// channel basepoints via the new function, or they were obtained via /// CommitmentTransaction.trust().keys() because we trusted the source of the /// pre-calculated keys. -#[derive(PartialEq, Clone)] +#[derive(PartialEq, Eq, Clone)] pub struct TxCreationKeys { /// The broadcaster's per-commitment public key which was used to derive the other keys. pub per_commitment_point: PublicKey, @@ -444,7 +459,7 @@ impl_writeable_tlv_based!(TxCreationKeys, { }); /// One counterparty's public keys which do not change over the life of a channel. -#[derive(Clone, PartialEq)] +#[derive(Clone, PartialEq, Eq)] pub struct ChannelPublicKeys { /// The public key which is used to sign all commitment transactions, as it appears in the /// on-chain channel lock-in 2-of-2 multisig output. @@ -525,8 +540,8 @@ pub fn get_revokeable_redeemscript(revocation_key: &PublicKey, contest_delay: u1 res } -#[derive(Clone, PartialEq)] /// Information about an HTLC as it appears in a commitment transaction +#[derive(Clone, Debug, PartialEq, Eq)] pub struct HTLCOutputInCommitment { /// Whether the HTLC was "offered" (ie outbound in relation to this commitment transaction). /// Note that this is not the same as whether it is ountbound *from us*. To determine that you @@ -699,7 +714,7 @@ pub fn build_htlc_transaction(commitment_txid: &Txid, feerate_per_kw: u32, conte /// Gets the witnessScript for the to_remote output when anchors are enabled. #[inline] -pub(crate) fn get_to_countersignatory_with_anchors_redeemscript(payment_point: &PublicKey) -> Script { +pub fn get_to_countersignatory_with_anchors_redeemscript(payment_point: &PublicKey) -> Script { Builder::new() .push_slice(&payment_point.serialize()[..]) .push_opcode(opcodes::all::OP_CHECKSIGVERIFY) @@ -726,6 +741,23 @@ pub fn get_anchor_redeemscript(funding_pubkey: &PublicKey) -> Script { .into_script() } +#[cfg(anchors)] +/// Locates the output with an anchor script paying to `funding_pubkey` within `commitment_tx`. +pub(crate) fn get_anchor_output<'a>(commitment_tx: &'a Transaction, funding_pubkey: &PublicKey) -> Option<(u32, &'a TxOut)> { + let anchor_script = chan_utils::get_anchor_redeemscript(funding_pubkey).to_v0_p2wsh(); + commitment_tx.output.iter().enumerate() + .find(|(_, txout)| txout.script_pubkey == anchor_script) + .map(|(idx, txout)| (idx as u32, txout)) +} + +/// Returns the witness required to satisfy and spend an anchor input. +pub fn build_anchor_input_witness(funding_key: &PublicKey, funding_sig: &Signature) -> Witness { + let anchor_redeem_script = chan_utils::get_anchor_redeemscript(funding_key); + let mut funding_sig = funding_sig.serialize_der().to_vec(); + funding_sig.push(EcdsaSighashType::All as u8); + Witness::from_vec(vec![funding_sig, anchor_redeem_script.to_bytes()]) +} + /// Per-channel data used to build transactions in conjunction with the per-commitment data (CommitmentTransaction). /// The fields are organized by holder/counterparty. /// @@ -882,6 +914,7 @@ impl Deref for HolderCommitmentTransaction { fn deref(&self) -> &Self::Target { &self.inner } } +impl Eq for HolderCommitmentTransaction {} impl PartialEq for HolderCommitmentTransaction { // We dont care whether we are signed in equality comparison fn eq(&self, o: &Self) -> bool { @@ -1007,7 +1040,7 @@ impl BuiltCommitmentTransaction { /// /// This class can be used inside a signer implementation to generate a signature given the relevant /// secret key. -#[derive(Clone, Hash, PartialEq)] +#[derive(Clone, Hash, PartialEq, Eq)] pub struct ClosingTransaction { to_holder_value_sat: u64, to_counterparty_value_sat: u64, @@ -1147,6 +1180,7 @@ pub struct CommitmentTransaction { built: BuiltCommitmentTransaction, } +impl Eq for CommitmentTransaction {} impl PartialEq for CommitmentTransaction { fn eq(&self, o: &Self) -> bool { let eq = self.commitment_number == o.commitment_number && @@ -1246,7 +1280,7 @@ impl CommitmentTransaction { let script = if opt_anchors { get_to_countersignatory_with_anchors_redeemscript(&countersignatory_pubkeys.payment_point).to_v0_p2wsh() } else { - get_p2wpkh_redeemscript(&countersignatory_pubkeys.payment_point) + Payload::p2wpkh(&BitcoinPublicKey::new(countersignatory_pubkeys.payment_point)).unwrap().script_pubkey() }; txouts.push(( TxOut { @@ -1552,25 +1586,21 @@ pub fn get_commitment_transaction_number_obscure_factor( | ((res[31] as u64) << 0 * 8) } -fn get_p2wpkh_redeemscript(key: &PublicKey) -> Script { - Builder::new().push_opcode(opcodes::all::OP_PUSHBYTES_0) - .push_slice(&WPubkeyHash::hash(&key.serialize())[..]) - .into_script() -} - #[cfg(test)] mod tests { use super::CounterpartyCommitmentSecrets; - use ::{hex, chain}; - use prelude::*; - use ln::chan_utils::{get_htlc_redeemscript, get_to_countersignatory_with_anchors_redeemscript, get_p2wpkh_redeemscript, CommitmentTransaction, TxCreationKeys, ChannelTransactionParameters, CounterpartyChannelTransactionParameters, HTLCOutputInCommitment}; + use crate::{hex, chain}; + use crate::prelude::*; + use crate::ln::chan_utils::{get_htlc_redeemscript, get_to_countersignatory_with_anchors_redeemscript, CommitmentTransaction, TxCreationKeys, ChannelTransactionParameters, CounterpartyChannelTransactionParameters, HTLCOutputInCommitment}; use bitcoin::secp256k1::{PublicKey, SecretKey, Secp256k1}; - use util::test_utils; - use chain::keysinterface::{KeysInterface, BaseSign}; + use crate::util::test_utils; + use crate::chain::keysinterface::{KeysInterface, BaseSign}; use bitcoin::{Network, Txid}; use bitcoin::hashes::Hash; - use ln::PaymentHash; + use crate::ln::PaymentHash; use bitcoin::hashes::hex::ToHex; + use bitcoin::util::address::Payload; + use bitcoin::PublicKey as BitcoinPublicKey; #[test] fn test_anchors() { @@ -1609,7 +1639,7 @@ mod tests { &mut htlcs_with_aux, &channel_parameters.as_holder_broadcastable() ); assert_eq!(tx.built.transaction.output.len(), 2); - assert_eq!(tx.built.transaction.output[1].script_pubkey, get_p2wpkh_redeemscript(&counterparty_pubkeys.payment_point)); + assert_eq!(tx.built.transaction.output[1].script_pubkey, Payload::p2wpkh(&BitcoinPublicKey::new(counterparty_pubkeys.payment_point)).unwrap().script_pubkey()); // Generate broadcaster and counterparty outputs as well as two anchors let tx = CommitmentTransaction::new_with_auxiliary_htlc_data(