X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fchan_utils.rs;h=d53863289bc5807464739f0707fbb390c25f9869;hb=989cb064b5279da3c9e0f3a121637d8bbed81bfb;hp=6e11dc42b819e64a61bd65d2f8f5421928bd0a4f;hpb=8f09e5a7ff464109ca1d7de065f56635c17bd0ac;p=rust-lightning diff --git a/lightning/src/ln/chan_utils.rs b/lightning/src/ln/chan_utils.rs index 6e11dc42..d5386328 100644 --- a/lightning/src/ln/chan_utils.rs +++ b/lightning/src/ln/chan_utils.rs @@ -12,8 +12,8 @@ use bitcoin::blockdata::script::{Script,Builder}; use bitcoin::blockdata::opcodes; -use bitcoin::blockdata::transaction::{TxIn,TxOut,OutPoint,Transaction, SigHashType}; -use bitcoin::util::bip143; +use bitcoin::blockdata::transaction::{TxIn,TxOut,OutPoint,Transaction, EcdsaSighashType}; +use bitcoin::util::sighash; use bitcoin::hashes::{Hash, HashEngine}; use bitcoin::hashes::sha256::Hash as Sha256; @@ -26,10 +26,10 @@ use util::ser::{Readable, Writeable, Writer}; use util::{byte_utils, transaction_utils}; use bitcoin::hash_types::WPubkeyHash; -use bitcoin::secp256k1::key::{SecretKey, PublicKey}; -use bitcoin::secp256k1::{Secp256k1, Signature, Message}; +use bitcoin::secp256k1::{SecretKey, PublicKey, Scalar}; +use bitcoin::secp256k1::{Secp256k1, ecdsa::Signature, Message}; use bitcoin::secp256k1::Error as SecpError; -use bitcoin::secp256k1; +use bitcoin::{PackedLockTime, secp256k1, Sequence, Witness}; use io; use prelude::*; @@ -39,15 +39,14 @@ use util::transaction_utils::sort_outputs; use 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(super) const HTLC_SUCCESS_TX_WEIGHT: u64 = 703; -pub(super) const HTLC_TIMEOUT_TX_WEIGHT: u64 = 663; - /// Gets the weight for an HTLC-Success transaction. #[inline] pub fn htlc_success_tx_weight(opt_anchors: bool) -> u64 { + const HTLC_SUCCESS_TX_WEIGHT: u64 = 703; const HTLC_SUCCESS_ANCHOR_TX_WEIGHT: u64 = 706; if opt_anchors { HTLC_SUCCESS_ANCHOR_TX_WEIGHT } else { HTLC_SUCCESS_TX_WEIGHT } } @@ -55,6 +54,7 @@ pub fn htlc_success_tx_weight(opt_anchors: bool) -> u64 { /// Gets the weight for an HTLC-Timeout transaction. #[inline] pub fn htlc_timeout_tx_weight(opt_anchors: bool) -> u64 { + const HTLC_TIMEOUT_TX_WEIGHT: u64 = 663; const HTLC_TIMEOUT_ANCHOR_TX_WEIGHT: u64 = 666; if opt_anchors { HTLC_TIMEOUT_ANCHOR_TX_WEIGHT } else { HTLC_TIMEOUT_TX_WEIGHT } } @@ -101,8 +101,8 @@ pub fn build_closing_transaction(to_holder_value_sat: u64, to_counterparty_value ins.push(TxIn { previous_output: funding_outpoint, script_sig: Script::new(), - sequence: 0xffffffff, - witness: Vec::new(), + sequence: Sequence::MAX, + witness: Witness::new(), }); ins }; @@ -132,19 +132,19 @@ pub fn build_closing_transaction(to_holder_value_sat: u64, to_counterparty_value Transaction { version: 2, - lock_time: 0, + lock_time: PackedLockTime::ZERO, input: txins, output: outputs, } } /// Implements the per-commitment secret storage scheme from -/// [BOLT 3](https://github.com/lightningnetwork/lightning-rfc/blob/dcbf8583976df087c79c3ce0b535311212e6812d/03-transactions.md#efficient-per-commitment-secret-storage). +/// [BOLT 3](https://github.com/lightning/bolts/blob/dcbf8583976df087c79c3ce0b535311212e6812d/03-transactions.md#efficient-per-commitment-secret-storage). /// -/// Allows us to keep track of all of the revocation secrets of counterarties in just 50*32 bytes +/// Allows us to keep track of all of the revocation secrets of our counterparty in just 50*32 bytes /// or so. #[derive(Clone)] -pub(crate) struct CounterpartyCommitmentSecrets { +pub struct CounterpartyCommitmentSecrets { old_secrets: [([u8; 32], u64); 49], } @@ -160,7 +160,8 @@ impl PartialEq for CounterpartyCommitmentSecrets { } impl CounterpartyCommitmentSecrets { - pub(crate) fn new() -> Self { + /// Creates a new empty `CounterpartyCommitmentSecrets` structure. + pub fn new() -> Self { Self { old_secrets: [([0; 32], 1 << 48); 49], } } @@ -174,7 +175,9 @@ impl CounterpartyCommitmentSecrets { 48 } - pub(crate) fn get_min_seen_secret(&self) -> u64 { + /// Returns the minimum index of all stored secrets. Note that indexes start + /// at 1 << 48 and get decremented by one for each new secret. + pub fn get_min_seen_secret(&self) -> u64 { //TODO This can be optimized? let mut min = 1 << 48; for &(_, idx) in self.old_secrets.iter() { @@ -198,7 +201,9 @@ impl CounterpartyCommitmentSecrets { res } - pub(crate) fn provide_secret(&mut self, idx: u64, secret: [u8; 32]) -> Result<(), ()> { + /// Inserts the `secret` at `idx`. Returns `Ok(())` if the secret + /// was generated in accordance with BOLT 3 and is consistent with previous secrets. + pub fn provide_secret(&mut self, idx: u64, secret: [u8; 32]) -> Result<(), ()> { let pos = Self::place_secret(idx); for i in 0..pos { let (old_secret, old_idx) = self.old_secrets[i as usize]; @@ -213,8 +218,9 @@ impl CounterpartyCommitmentSecrets { Ok(()) } - /// Can only fail if idx is < get_min_seen_secret - pub(crate) fn get_secret(&self, idx: u64) -> Option<[u8; 32]> { + /// Returns the secret at `idx`. + /// Returns `None` if `idx` is < [`CounterpartyCommitmentSecrets::get_min_seen_secret`]. + pub fn get_secret(&self, idx: u64) -> Option<[u8; 32]> { for i in 0..self.old_secrets.len() { if (idx & (!((1 << i) - 1))) == self.old_secrets[i].1 { return Some(Self::derive_secret(self.old_secrets[i].0, i as u8, idx)) @@ -258,9 +264,7 @@ pub fn derive_private_key(secp_ctx: &Secp256k1, per_co sha.input(&PublicKey::from_secret_key(&secp_ctx, &base_secret).serialize()); let res = Sha256::from_engine(sha).into_inner(); - let mut key = base_secret.clone(); - key.add_assign(&res)?; - Ok(key) + base_secret.clone().add_tweak(&Scalar::from_be_bytes(res).unwrap()) } /// Derives a per-commitment-transaction public key (eg an htlc key or a delayed_payment key) @@ -307,12 +311,9 @@ pub fn derive_private_revocation_key(secp_ctx: &Secp256k1 Sha256::from_engine(sha).into_inner() }; - let mut countersignatory_contrib = countersignatory_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) + let countersignatory_contrib = countersignatory_revocation_base_secret.clone().mul_tweak(&Scalar::from_be_bytes(rev_append_commit_hash_key).unwrap())?; + let broadcaster_contrib = per_commitment_secret.clone().mul_tweak(&Scalar::from_be_bytes(commit_append_rev_hash_key).unwrap())?; + countersignatory_contrib.add_tweak(&Scalar::from_be_bytes(broadcaster_contrib.secret_bytes()).unwrap()) } /// Derives a per-commitment-transaction revocation public key from its constituent parts. This is @@ -342,10 +343,8 @@ pub fn derive_public_revocation_key(secp_ctx: &Secp2 Sha256::from_engine(sha).into_inner() }; - let mut countersignatory_contrib = countersignatory_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)?; + let countersignatory_contrib = countersignatory_revocation_base_point.clone().mul_tweak(&secp_ctx, &Scalar::from_be_bytes(rev_append_commit_hash_key).unwrap())?; + let broadcaster_contrib = per_commitment_point.clone().mul_tweak(&secp_ctx, &Scalar::from_be_bytes(commit_append_rev_hash_key).unwrap())?; countersignatory_contrib.combine(&broadcaster_contrib) } @@ -608,8 +607,8 @@ pub fn build_htlc_transaction(commitment_txid: &Txid, feerate_per_kw: u32, conte vout: htlc.transaction_output_index.expect("Can't build an HTLC transaction for a dust output"), }, script_sig: Script::new(), - sequence: if opt_anchors { 1 } else { 0 }, - witness: Vec::new(), + sequence: Sequence(if opt_anchors { 1 } else { 0 }), + witness: Witness::new(), }); let weight = if htlc.offered { @@ -627,7 +626,7 @@ pub fn build_htlc_transaction(commitment_txid: &Txid, feerate_per_kw: u32, conte Transaction { version: 2, - lock_time: if htlc.offered { htlc.cltv_expiry } else { 0 }, + lock_time: PackedLockTime(if htlc.offered { htlc.cltv_expiry } else { 0 }), input: txins, output: txouts, } @@ -836,7 +835,7 @@ impl HolderCommitmentTransaction { pub fn dummy() -> Self { let secp_ctx = Secp256k1::new(); let dummy_key = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); - let dummy_sig = secp_ctx.sign(&secp256k1::Message::from_slice(&[42; 32]).unwrap(), &SecretKey::from_slice(&[42; 32]).unwrap()); + let dummy_sig = sign(&secp_ctx, &secp256k1::Message::from_slice(&[42; 32]).unwrap(), &SecretKey::from_slice(&[42; 32]).unwrap()); let keys = TxCreationKeys { per_commitment_point: dummy_key.clone(), @@ -857,7 +856,7 @@ impl HolderCommitmentTransaction { holder_selected_contest_delay: 0, is_outbound_from_holder: false, counterparty_parameters: Some(CounterpartyChannelTransactionParameters { pubkeys: channel_pubkeys.clone(), selected_contest_delay: 0 }), - funding_outpoint: Some(chain::transaction::OutPoint { txid: Default::default(), index: 0 }), + funding_outpoint: Some(chain::transaction::OutPoint { txid: Txid::all_zeros(), index: 0 }), opt_anchors: None }; let mut htlcs_with_aux: Vec<(_, ())> = Vec::new(); @@ -885,16 +884,18 @@ impl HolderCommitmentTransaction { // First push the multisig dummy, note that due to BIP147 (NULLDUMMY) it must be a zero-length element. let mut tx = self.inner.built.transaction.clone(); tx.input[0].witness.push(Vec::new()); + let mut ser_holder_sig = holder_sig.serialize_der().to_vec(); + ser_holder_sig.push(EcdsaSighashType::All as u8); + let mut ser_cp_sig = self.counterparty_sig.serialize_der().to_vec(); + ser_cp_sig.push(EcdsaSighashType::All as u8); if self.holder_sig_first { - tx.input[0].witness.push(holder_sig.serialize_der().to_vec()); - tx.input[0].witness.push(self.counterparty_sig.serialize_der().to_vec()); + tx.input[0].witness.push(ser_holder_sig); + tx.input[0].witness.push(ser_cp_sig); } else { - tx.input[0].witness.push(self.counterparty_sig.serialize_der().to_vec()); - tx.input[0].witness.push(holder_sig.serialize_der().to_vec()); + tx.input[0].witness.push(ser_cp_sig); + tx.input[0].witness.push(ser_holder_sig); } - tx.input[0].witness[1].push(SigHashType::All as u8); - tx.input[0].witness[2].push(SigHashType::All as u8); tx.input[0].witness.push(funding_redeemscript.as_bytes().to_vec()); tx @@ -923,7 +924,7 @@ impl BuiltCommitmentTransaction { /// /// This can be used to verify a signature. pub fn get_sighash_all(&self, funding_redeemscript: &Script, channel_value_satoshis: u64) -> Message { - let sighash = &bip143::SigHashCache::new(&self.transaction).signature_hash(0, funding_redeemscript, channel_value_satoshis, SigHashType::All)[..]; + let sighash = &sighash::SighashCache::new(&self.transaction).segwit_signature_hash(0, funding_redeemscript, channel_value_satoshis, EcdsaSighashType::All).unwrap()[..]; hash_to_message!(sighash) } @@ -931,7 +932,7 @@ impl BuiltCommitmentTransaction { /// because we are about to broadcast a holder transaction. pub fn sign(&self, funding_key: &SecretKey, funding_redeemscript: &Script, channel_value_satoshis: u64, secp_ctx: &Secp256k1) -> Signature { let sighash = self.get_sighash_all(funding_redeemscript, channel_value_satoshis); - secp_ctx.sign(&sighash, funding_key) + sign(secp_ctx, &sighash, funding_key) } } @@ -1047,7 +1048,7 @@ impl<'a> TrustedClosingTransaction<'a> { /// /// This can be used to verify a signature. pub fn get_sighash_all(&self, funding_redeemscript: &Script, channel_value_satoshis: u64) -> Message { - let sighash = &bip143::SigHashCache::new(&self.inner.built).signature_hash(0, funding_redeemscript, channel_value_satoshis, SigHashType::All)[..]; + let sighash = &sighash::SighashCache::new(&self.inner.built).segwit_signature_hash(0, funding_redeemscript, channel_value_satoshis, EcdsaSighashType::All).unwrap()[..]; hash_to_message!(sighash) } @@ -1055,7 +1056,7 @@ impl<'a> TrustedClosingTransaction<'a> { /// because we are about to broadcast a holder transaction. pub fn sign(&self, funding_key: &SecretKey, funding_redeemscript: &Script, channel_value_satoshis: u64, secp_ctx: &Secp256k1) -> Signature { let sighash = self.get_sighash_all(funding_redeemscript, channel_value_satoshis); - secp_ctx.sign(&sighash, funding_key) + sign(secp_ctx, &sighash, funding_key) } } @@ -1159,7 +1160,7 @@ impl CommitmentTransaction { fn make_transaction(obscured_commitment_transaction_number: u64, txins: Vec, outputs: Vec) -> Transaction { Transaction { version: 2, - lock_time: ((0x20 as u32) << 8 * 3) | ((obscured_commitment_transaction_number & 0xffffffu64) as u32), + lock_time: PackedLockTime(((0x20 as u32) << 8 * 3) | ((obscured_commitment_transaction_number & 0xffffffu64) as u32)), input: txins, output: outputs, } @@ -1246,7 +1247,7 @@ impl CommitmentTransaction { if let &Some(ref b_htlcout) = b { a_htlcout.cltv_expiry.cmp(&b_htlcout.cltv_expiry) // Note that due to hash collisions, we have to have a fallback comparison - // here for fuzztarget mode (otherwise at least chanmon_fail_consistency + // here for fuzzing mode (otherwise at least chanmon_fail_consistency // may fail)! .then(a_htlcout.payment_hash.0.cmp(&b_htlcout.payment_hash.0)) // For non-HTLC outputs, if they're copying our SPK we don't really care if we @@ -1283,9 +1284,9 @@ impl CommitmentTransaction { ins.push(TxIn { previous_output: channel_parameters.funding_outpoint(), script_sig: Script::new(), - sequence: ((0x80 as u32) << 8 * 3) - | ((obscured_commitment_transaction_number >> 3 * 8) as u32), - witness: Vec::new(), + sequence: Sequence(((0x80 as u32) << 8 * 3) + | ((obscured_commitment_transaction_number >> 3 * 8) as u32)), + witness: Witness::new(), }); ins }; @@ -1395,7 +1396,7 @@ impl<'a> TrustedCommitmentTransaction<'a> { /// /// The returned Vec has one entry for each HTLC, and in the same order. /// - /// This function is only valid in the holder commitment context, it always uses SigHashType::All. + /// This function is only valid in the holder commitment context, it always uses EcdsaSighashType::All. pub fn get_htlc_sigs(&self, htlc_base_key: &SecretKey, channel_parameters: &DirectedChannelTransactionParameters, secp_ctx: &Secp256k1) -> Result, ()> { let inner = self.inner; let keys = &inner.keys; @@ -1409,8 +1410,8 @@ impl<'a> TrustedCommitmentTransaction<'a> { let htlc_redeemscript = get_htlc_redeemscript_with_explicit_keys(&this_htlc, self.opt_anchors(), &keys.broadcaster_htlc_key, &keys.countersignatory_htlc_key, &keys.revocation_key); - let sighash = hash_to_message!(&bip143::SigHashCache::new(&htlc_tx).signature_hash(0, &htlc_redeemscript, this_htlc.amount_msat / 1000, SigHashType::All)[..]); - ret.push(secp_ctx.sign(&sighash, &holder_htlc_key)); + let sighash = hash_to_message!(&sighash::SighashCache::new(&htlc_tx).segwit_signature_hash(0, &htlc_redeemscript, this_htlc.amount_msat / 1000, EcdsaSighashType::All).unwrap()[..]); + ret.push(sign(secp_ctx, &sighash, &holder_htlc_key)); } Ok(ret) } @@ -1431,15 +1432,17 @@ impl<'a> TrustedCommitmentTransaction<'a> { let htlc_redeemscript = get_htlc_redeemscript_with_explicit_keys(&this_htlc, self.opt_anchors(), &keys.broadcaster_htlc_key, &keys.countersignatory_htlc_key, &keys.revocation_key); - let sighashtype = if self.opt_anchors() { SigHashType::SinglePlusAnyoneCanPay } else { SigHashType::All }; + let sighashtype = if self.opt_anchors() { EcdsaSighashType::SinglePlusAnyoneCanPay } else { EcdsaSighashType::All }; // 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()); - htlc_tx.input[0].witness.push(counterparty_signature.serialize_der().to_vec()); - htlc_tx.input[0].witness.push(signature.serialize_der().to_vec()); - htlc_tx.input[0].witness[1].push(sighashtype as u8); - htlc_tx.input[0].witness[2].push(SigHashType::All as u8); + let mut cp_sig_ser = counterparty_signature.serialize_der().to_vec(); + cp_sig_ser.push(sighashtype as u8); + htlc_tx.input[0].witness.push(cp_sig_ser); + let mut holder_sig_ser = signature.serialize_der().to_vec(); + holder_sig_ser.push(EcdsaSighashType::All as u8); + htlc_tx.input[0].witness.push(holder_sig_ser); if this_htlc.offered { // Due to BIP146 (MINIMALIF) this must be a zero-length element to relay. @@ -1498,7 +1501,8 @@ mod tests { use bitcoin::secp256k1::{PublicKey, SecretKey, Secp256k1}; use util::test_utils; use chain::keysinterface::{KeysInterface, BaseSign}; - use bitcoin::Network; + use bitcoin::{Network, Txid}; + use bitcoin::hashes::Hash; use ln::PaymentHash; use bitcoin::hashes::hex::ToHex; @@ -1523,7 +1527,7 @@ mod tests { holder_selected_contest_delay: 0, is_outbound_from_holder: false, counterparty_parameters: Some(CounterpartyChannelTransactionParameters { pubkeys: counterparty_pubkeys.clone(), selected_contest_delay: 0 }), - funding_outpoint: Some(chain::transaction::OutPoint { txid: Default::default(), index: 0 }), + funding_outpoint: Some(chain::transaction::OutPoint { txid: Txid::all_zeros(), index: 0 }), opt_anchors: None };