X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;ds=sidebyside;f=lightning%2Fsrc%2Fln%2Fonchaintx.rs;h=c99dc87d6cb4225a2223ddf2d5a809c0dc78e213;hb=9dbce1c316f6ebbfb905148b646ae513325fe039;hp=7ee0ccb100fb145b33a7d30cf1561966adb77ea2;hpb=824e318be3c58e2a316ab62e0ede0e343c9b9031;p=rust-lightning diff --git a/lightning/src/ln/onchaintx.rs b/lightning/src/ln/onchaintx.rs index 7ee0ccb1..c99dc87d 100644 --- a/lightning/src/ln/onchaintx.rs +++ b/lightning/src/ln/onchaintx.rs @@ -6,19 +6,17 @@ use bitcoin::blockdata::transaction::{Transaction, TxIn, TxOut, SigHashType}; use bitcoin::blockdata::transaction::OutPoint as BitcoinOutPoint; use bitcoin::blockdata::script::Script; -use bitcoin::util::bip143; use bitcoin::hash_types::Txid; use bitcoin::secp256k1::{Secp256k1, Signature}; use bitcoin::secp256k1; -use bitcoin::secp256k1::key::PublicKey; use ln::msgs::DecodeError; use ln::channelmonitor::{ANTI_REORG_DELAY, CLTV_SHARED_CLAIM_BUFFER, InputMaterial, ClaimRequest}; use ln::channelmanager::PaymentPreimage; use ln::chan_utils; -use ln::chan_utils::{TxCreationKeys, LocalCommitmentTransaction, HTLCOutputInCommitment}; +use ln::chan_utils::{TxCreationKeys, LocalCommitmentTransaction}; use chain::chaininterface::{FeeEstimator, BroadcasterInterface, ConfirmationTarget, MIN_RELAY_FEE_SAT_PER_1000_WEIGHT}; use chain::keysinterface::ChannelKeys; use util::logger::Logger; @@ -49,14 +47,6 @@ enum OnchainEvent { } } -/// Cache remote basepoint to compute any transaction on -/// remote outputs, either justice or preimage/timeout transactions. -struct RemoteTxCache { - remote_delayed_payment_base_key: PublicKey, - remote_htlc_base_key: PublicKey, - per_htlc: HashMap> -} - /// Higher-level cache structure needed to re-generate bumped claim txn if needed #[derive(Clone, PartialEq)] pub struct ClaimTxBumpMaterial { @@ -250,9 +240,7 @@ pub struct OnchainTxHandler { local_htlc_sigs: Option>>, prev_local_commitment: Option, prev_local_htlc_sigs: Option>>, - local_csv: u16, - remote_tx_cache: RemoteTxCache, - remote_csv: u16, + on_local_tx_csv: u16, key_storage: ChanSigner, @@ -296,19 +284,7 @@ impl OnchainTxHandler { self.prev_local_commitment.write(writer)?; self.prev_local_htlc_sigs.write(writer)?; - self.local_csv.write(writer)?; - - self.remote_tx_cache.remote_delayed_payment_base_key.write(writer)?; - self.remote_tx_cache.remote_htlc_base_key.write(writer)?; - writer.write_all(&byte_utils::be64_to_array(self.remote_tx_cache.per_htlc.len() as u64))?; - for (ref txid, ref htlcs) in self.remote_tx_cache.per_htlc.iter() { - writer.write_all(&txid[..])?; - writer.write_all(&byte_utils::be64_to_array(htlcs.len() as u64))?; - for &ref htlc in htlcs.iter() { - htlc.write(writer)?; - } - } - self.remote_csv.write(writer)?; + self.on_local_tx_csv.write(writer)?; self.key_storage.write(writer)?; @@ -356,32 +332,7 @@ impl Readable for OnchainTxHandler Readable for OnchainTxHandler Readable for OnchainTxHandler OnchainTxHandler { - pub(super) fn new(destination_script: Script, keys: ChanSigner, local_csv: u16, remote_delayed_payment_base_key: PublicKey, remote_htlc_base_key: PublicKey, remote_csv: u16) -> Self { + pub(super) fn new(destination_script: Script, keys: ChanSigner, on_local_tx_csv: u16) -> Self { let key_storage = keys; - let remote_tx_cache = RemoteTxCache { - remote_delayed_payment_base_key, - remote_htlc_base_key, - per_htlc: HashMap::new(), - }; - OnchainTxHandler { destination_script, local_commitment: None, local_htlc_sigs: None, prev_local_commitment: None, prev_local_htlc_sigs: None, - local_csv, - remote_tx_cache, - remote_csv, + on_local_tx_csv, key_storage, pending_claim_requests: HashMap::new(), claimable_outpoints: HashMap::new(), @@ -597,9 +538,9 @@ impl OnchainTxHandler { inputs_witnesses_weight += Self::get_witnesses_weight(&[*input_descriptor]); amt += *amount; }, - &InputMaterial::RemoteHTLC { ref preimage, ref amount, .. } => { + &InputMaterial::RemoteHTLC { ref preimage, ref htlc, .. } => { inputs_witnesses_weight += Self::get_witnesses_weight(if preimage.is_some() { &[InputDescriptors::OfferedHTLC] } else { &[InputDescriptors::ReceivedHTLC] }); - amt += *amount; + amt += htlc.amount_msat / 1000; }, &InputMaterial::LocalHTLC { .. } => { dynamic_fee = false; @@ -632,56 +573,48 @@ impl OnchainTxHandler { for (i, (outp, per_outp_material)) in cached_claim_datas.per_input_material.iter().enumerate() { match per_outp_material { - &InputMaterial::Revoked { ref per_commitment_point, ref key, ref input_descriptor, ref amount } => { - if let Ok(chan_keys) = TxCreationKeys::new(&self.secp_ctx, &per_commitment_point, &self.remote_tx_cache.remote_delayed_payment_base_key, &self.remote_tx_cache.remote_htlc_base_key, &self.key_storage.pubkeys().revocation_basepoint, &self.key_storage.pubkeys().htlc_basepoint) { - - let mut this_htlc = None; - if *input_descriptor != InputDescriptors::RevokedOutput { - if let Some(htlcs) = self.remote_tx_cache.per_htlc.get(&outp.txid) { - for htlc in htlcs { - if htlc.transaction_output_index.unwrap() == outp.vout { - this_htlc = Some(htlc); - } - } - } - } + &InputMaterial::Revoked { ref per_commitment_point, ref remote_delayed_payment_base_key, ref remote_htlc_base_key, ref per_commitment_key, ref input_descriptor, ref amount, ref htlc, ref on_remote_tx_csv } => { + if let Ok(chan_keys) = TxCreationKeys::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 *input_descriptor != InputDescriptors::RevokedOutput && this_htlc.is_some() { - chan_utils::get_htlc_redeemscript_with_explicit_keys(&this_htlc.unwrap(), &chan_keys.a_htlc_key, &chan_keys.b_htlc_key, &chan_keys.revocation_key) - } else if *input_descriptor != InputDescriptors::RevokedOutput { - return None; + 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) } else { - chan_utils::get_revokeable_redeemscript(&chan_keys.revocation_key, self.remote_csv, &chan_keys.a_delayed_payment_key) + chan_utils::get_revokeable_redeemscript(&chan_keys.revocation_key, *on_remote_tx_csv, &chan_keys.a_delayed_payment_key) }; - let sighash_parts = bip143::SighashComponents::new(&bumped_tx); - let sighash = hash_to_message!(&sighash_parts.sighash_all(&bumped_tx.input[i], &witness_script, *amount)[..]); - let sig = self.secp_ctx.sign(&sighash, &key); - bumped_tx.input[i].witness.push(sig.serialize_der().to_vec()); - bumped_tx.input[i].witness[0].push(SigHashType::All as u8); - if *input_descriptor != InputDescriptors::RevokedOutput { - bumped_tx.input[i].witness.push(chan_keys.revocation_key.clone().serialize().to_vec()); - } else { - bumped_tx.input[i].witness.push(vec!(1)); - } - bumped_tx.input[i].witness.push(witness_script.clone().into_bytes()); + if let Ok(sig) = self.key_storage.sign_justice_transaction(&bumped_tx, i, *amount, &per_commitment_key, htlc, *on_remote_tx_csv, &self.secp_ctx) { + bumped_tx.input[i].witness.push(sig.serialize_der().to_vec()); + bumped_tx.input[i].witness[0].push(SigHashType::All as u8); + if htlc.is_some() { + bumped_tx.input[i].witness.push(chan_keys.revocation_key.clone().serialize().to_vec()); + } else { + bumped_tx.input[i].witness.push(vec!(1)); + } + bumped_tx.input[i].witness.push(witness_script.clone().into_bytes()); + } else { return None; } + //TODO: panic ? + log_trace!(logger, "Going to broadcast Penalty Transaction {} claiming revoked {} output {} from {} with new feerate {}...", bumped_tx.txid(), if *input_descriptor == InputDescriptors::RevokedOutput { "to_local" } else if *input_descriptor == InputDescriptors::RevokedOfferedHTLC { "offered" } else if *input_descriptor == InputDescriptors::RevokedReceivedHTLC { "received" } else { "" }, outp.vout, outp.txid, new_feerate); } }, - &InputMaterial::RemoteHTLC { ref witness_script, ref key, ref preimage, ref amount, ref locktime } => { - if !preimage.is_some() { bumped_tx.lock_time = *locktime }; // Right now we don't aggregate time-locked transaction, if we do we should set lock_time before to avoid breaking hash computation - let sighash_parts = bip143::SighashComponents::new(&bumped_tx); - let sighash = hash_to_message!(&sighash_parts.sighash_all(&bumped_tx.input[i], &witness_script, *amount)[..]); - let sig = self.secp_ctx.sign(&sighash, &key); - bumped_tx.input[i].witness.push(sig.serialize_der().to_vec()); - bumped_tx.input[i].witness[0].push(SigHashType::All as u8); - if let &Some(preimage) = preimage { - bumped_tx.input[i].witness.push(preimage.clone().0.to_vec()); - } else { - bumped_tx.input[i].witness.push(vec![]); + &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::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); + + 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) { + bumped_tx.input[i].witness.push(sig.serialize_der().to_vec()); + bumped_tx.input[i].witness[0].push(SigHashType::All as u8); + if let &Some(preimage) = preimage { + bumped_tx.input[i].witness.push(preimage.0.to_vec()); + } else { + // Due to BIP146 (MINIMALIF) this must be a zero-length element to relay. + bumped_tx.input[i].witness.push(vec![]); + } + bumped_tx.input[i].witness.push(witness_script.clone().into_bytes()); + } + log_trace!(logger, "Going to broadcast Claim Transaction {} claiming remote {} htlc output {} from {} with new feerate {}...", bumped_tx.txid(), if preimage.is_some() { "offered" } else { "received" }, outp.vout, outp.txid, new_feerate); } - bumped_tx.input[i].witness.push(witness_script.clone().into_bytes()); - log_trace!(logger, "Going to broadcast Claim Transaction {} claiming remote {} htlc output {} from {} with new feerate {}...", bumped_tx.txid(), if preimage.is_some() { "offered" } else { "received" }, outp.vout, outp.txid, new_feerate); }, _ => unreachable!() } @@ -951,7 +884,7 @@ impl OnchainTxHandler { fn sign_latest_local_htlcs(&mut self) { if let Some(ref local_commitment) = self.local_commitment { - if let Ok(sigs) = self.key_storage.sign_local_commitment_htlc_transactions(local_commitment, self.local_csv, &self.secp_ctx) { + if let Ok(sigs) = self.key_storage.sign_local_commitment_htlc_transactions(local_commitment, self.on_local_tx_csv, &self.secp_ctx) { self.local_htlc_sigs = Some(Vec::new()); let ret = self.local_htlc_sigs.as_mut().unwrap(); for (htlc_idx, (local_sig, &(ref htlc, _))) in sigs.iter().zip(local_commitment.per_htlc.iter()).enumerate() { @@ -967,7 +900,7 @@ impl OnchainTxHandler { } fn sign_prev_local_htlcs(&mut self) { if let Some(ref local_commitment) = self.prev_local_commitment { - if let Ok(sigs) = self.key_storage.sign_local_commitment_htlc_transactions(local_commitment, self.local_csv, &self.secp_ctx) { + if let Ok(sigs) = self.key_storage.sign_local_commitment_htlc_transactions(local_commitment, self.on_local_tx_csv, &self.secp_ctx) { self.prev_local_htlc_sigs = Some(Vec::new()); let ret = self.prev_local_htlc_sigs.as_mut().unwrap(); for (htlc_idx, (local_sig, &(ref htlc, _))) in sigs.iter().zip(local_commitment.per_htlc.iter()).enumerate() { @@ -997,10 +930,6 @@ impl OnchainTxHandler { } } - pub(super) fn provide_latest_remote_tx(&mut self, commitment_txid: Txid, htlcs: Vec) { - self.remote_tx_cache.per_htlc.insert(commitment_txid, htlcs); - } - #[cfg(test)] pub(super) fn get_fully_signed_copy_local_tx(&mut self, funding_redeemscript: &Script) -> Option { if let Some(ref mut local_commitment) = self.local_commitment { @@ -1023,7 +952,7 @@ impl OnchainTxHandler { if let &Some(ref htlc_sigs) = &self.local_htlc_sigs { let &(ref htlc_idx, ref htlc_sig) = htlc_sigs[outp.vout as usize].as_ref().unwrap(); htlc_tx = Some(self.local_commitment.as_ref().unwrap() - .get_signed_htlc_tx(*htlc_idx, htlc_sig, preimage, self.local_csv)); + .get_signed_htlc_tx(*htlc_idx, htlc_sig, preimage, self.on_local_tx_csv)); } } } @@ -1034,7 +963,7 @@ impl OnchainTxHandler { if let &Some(ref htlc_sigs) = &self.prev_local_htlc_sigs { let &(ref htlc_idx, ref htlc_sig) = htlc_sigs[outp.vout as usize].as_ref().unwrap(); htlc_tx = Some(self.prev_local_commitment.as_ref().unwrap() - .get_signed_htlc_tx(*htlc_idx, htlc_sig, preimage, self.local_csv)); + .get_signed_htlc_tx(*htlc_idx, htlc_sig, preimage, self.on_local_tx_csv)); } } }