X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fchain%2Fchannelmonitor.rs;h=80cd9cb9d45958629e1789513190a4de63b87e7b;hb=b76040718f954fa7baae42c7070e3ff6ac8add3c;hp=3f7a1055b6dc3f1dba4d21387051cbe0751293e9;hpb=70ae45fea030ed1d2064918c7b023aa142387bc8;p=rust-lightning diff --git a/lightning/src/chain/channelmonitor.rs b/lightning/src/chain/channelmonitor.rs index 3f7a1055..80cd9cb9 100644 --- a/lightning/src/chain/channelmonitor.rs +++ b/lightning/src/chain/channelmonitor.rs @@ -40,7 +40,7 @@ use ln::chan_utils::{CounterpartyCommitmentSecrets, HTLCOutputInCommitment, HTLC use ln::channelmanager::HTLCSource; use chain; use chain::{BestBlock, WatchedOutput}; -use chain::chaininterface::{BroadcasterInterface, FeeEstimator}; +use chain::chaininterface::{BroadcasterInterface, FeeEstimator, LowerBoundedFeeEstimator}; use chain::transaction::{OutPoint, TransactionData}; use chain::keysinterface::{SpendableOutputDescriptor, StaticPaymentOutputDescriptor, DelayedPaymentOutputDescriptor, Sign, KeysInterface}; use chain::onchaintx::OnchainTxHandler; @@ -722,6 +722,9 @@ pub(crate) struct ChannelMonitorImpl { // the full block_connected). best_block: BestBlock, + /// The node_id of our counterparty + counterparty_node_id: Option, + secp_ctx: Secp256k1, //TODO: dedup this a bit... } @@ -954,6 +957,7 @@ impl Writeable for ChannelMonitorImpl { (3, self.htlcs_resolved_on_chain, vec_type), (5, self.pending_monitor_events, vec_type), (7, self.funding_spend_seen, required), + (9, self.counterparty_node_id, option), }); Ok(()) @@ -967,7 +971,7 @@ impl ChannelMonitor { funding_redeemscript: Script, channel_value_satoshis: u64, commitment_transaction_number_obscure_factor: u64, initial_holder_commitment_tx: HolderCommitmentTransaction, - best_block: BestBlock) -> ChannelMonitor { + best_block: BestBlock, counterparty_node_id: PublicKey) -> ChannelMonitor { assert!(commitment_transaction_number_obscure_factor <= (1 << 48)); let payment_key_hash = WPubkeyHash::hash(&keys.pubkeys().payment_point.serialize()); @@ -1057,6 +1061,7 @@ impl ChannelMonitor { htlcs_resolved_on_chain: Vec::new(), best_block, + counterparty_node_id: Some(counterparty_node_id), secp_ctx, }), @@ -1099,7 +1104,7 @@ impl ChannelMonitor { payment_hash: &PaymentHash, payment_preimage: &PaymentPreimage, broadcaster: &B, - fee_estimator: &F, + fee_estimator: &LowerBoundedFeeEstimator, logger: &L, ) where B::Target: BroadcasterInterface, @@ -1295,8 +1300,9 @@ impl ChannelMonitor { F::Target: FeeEstimator, L::Target: Logger, { + let bounded_fee_estimator = LowerBoundedFeeEstimator::new(fee_estimator); self.inner.lock().unwrap().transactions_confirmed( - header, txdata, height, broadcaster, fee_estimator, logger) + header, txdata, height, broadcaster, &bounded_fee_estimator, logger) } /// Processes a transaction that was reorganized out of the chain. @@ -1316,8 +1322,9 @@ impl ChannelMonitor { F::Target: FeeEstimator, L::Target: Logger, { + let bounded_fee_estimator = LowerBoundedFeeEstimator::new(fee_estimator); self.inner.lock().unwrap().transaction_unconfirmed( - txid, broadcaster, fee_estimator, logger); + txid, broadcaster, &bounded_fee_estimator, logger); } /// Updates the monitor with the current best chain tip, returning new outputs to watch. See @@ -1340,8 +1347,9 @@ impl ChannelMonitor { F::Target: FeeEstimator, L::Target: Logger, { + let bounded_fee_estimator = LowerBoundedFeeEstimator::new(fee_estimator); self.inner.lock().unwrap().best_block_updated( - header, height, broadcaster, fee_estimator, logger) + header, height, broadcaster, &bounded_fee_estimator, logger) } /// Returns the set of txids that should be monitored for re-organization out of the chain. @@ -1729,6 +1737,26 @@ macro_rules! fail_unbroadcast_htlcs { } } } +// In the `test_invalid_funding_tx` test, we need a bogus script which matches the HTLC-Accepted +// witness length match (ie is 136 bytes long). We generate one here which we also use in some +// in-line tests later. + +#[cfg(test)] +pub fn deliberately_bogus_accepted_htlc_witness_program() -> Vec { + let mut ret = [opcodes::all::OP_NOP.into_u8(); 136]; + ret[131] = opcodes::all::OP_DROP.into_u8(); + ret[132] = opcodes::all::OP_DROP.into_u8(); + ret[133] = opcodes::all::OP_DROP.into_u8(); + ret[134] = opcodes::all::OP_DROP.into_u8(); + ret[135] = opcodes::OP_TRUE.into_u8(); + Vec::from(&ret[..]) +} + +#[cfg(test)] +pub fn deliberately_bogus_accepted_htlc_witness() -> Vec> { + vec![Vec::new(), Vec::new(), Vec::new(), Vec::new(), deliberately_bogus_accepted_htlc_witness_program().into()].into() +} + impl ChannelMonitorImpl { /// Inserts a revocation secret into this channel monitor. Prunes old preimages if neither /// needed by holder commitment transactions HTCLs nor by counterparty ones. Unless we haven't already seen @@ -1857,7 +1885,9 @@ impl ChannelMonitorImpl { /// Provides a payment_hash->payment_preimage mapping. Will be automatically pruned when all /// commitment_tx_infos which contain the payment hash have been revoked. - fn provide_payment_preimage(&mut self, payment_hash: &PaymentHash, payment_preimage: &PaymentPreimage, broadcaster: &B, fee_estimator: &F, logger: &L) + fn provide_payment_preimage( + &mut self, payment_hash: &PaymentHash, payment_preimage: &PaymentPreimage, broadcaster: &B, + fee_estimator: &LowerBoundedFeeEstimator, logger: &L) where B::Target: BroadcasterInterface, F::Target: FeeEstimator, L::Target: Logger, @@ -1955,7 +1985,8 @@ impl ChannelMonitorImpl { }, ChannelMonitorUpdateStep::PaymentPreimage { payment_preimage } => { log_trace!(logger, "Updating ChannelMonitor with payment preimage"); - self.provide_payment_preimage(&PaymentHash(Sha256::hash(&payment_preimage.0[..]).into_inner()), &payment_preimage, broadcaster, fee_estimator, logger) + let bounded_fee_estimator = LowerBoundedFeeEstimator::new(fee_estimator); + self.provide_payment_preimage(&PaymentHash(Sha256::hash(&payment_preimage.0[..]).into_inner()), &payment_preimage, broadcaster, &bounded_fee_estimator, logger) }, ChannelMonitorUpdateStep::CommitmentSecret { idx, secret } => { log_trace!(logger, "Updating ChannelMonitor with commitment secret"); @@ -2381,7 +2412,8 @@ impl ChannelMonitorImpl { let block_hash = header.block_hash(); self.best_block = BestBlock::new(block_hash, height); - self.transactions_confirmed(header, txdata, height, broadcaster, fee_estimator, logger) + let bounded_fee_estimator = LowerBoundedFeeEstimator::new(fee_estimator); + self.transactions_confirmed(header, txdata, height, broadcaster, &bounded_fee_estimator, logger) } fn best_block_updated( @@ -2389,7 +2421,7 @@ impl ChannelMonitorImpl { header: &BlockHeader, height: u32, broadcaster: B, - fee_estimator: F, + fee_estimator: &LowerBoundedFeeEstimator, logger: L, ) -> Vec where @@ -2416,7 +2448,7 @@ impl ChannelMonitorImpl { txdata: &TransactionData, height: u32, broadcaster: B, - fee_estimator: F, + fee_estimator: &LowerBoundedFeeEstimator, logger: L, ) -> Vec where @@ -2513,7 +2545,7 @@ impl ChannelMonitorImpl { mut watch_outputs: Vec, mut claimable_outpoints: Vec, broadcaster: &B, - fee_estimator: &F, + fee_estimator: &LowerBoundedFeeEstimator, logger: &L, ) -> Vec where @@ -2651,7 +2683,8 @@ impl ChannelMonitorImpl { //- maturing spendable output has transaction paying us has been disconnected self.onchain_events_awaiting_threshold_conf.retain(|ref entry| entry.height < height); - self.onchain_tx_handler.block_disconnected(height, broadcaster, fee_estimator, logger); + let bounded_fee_estimator = LowerBoundedFeeEstimator::new(fee_estimator); + self.onchain_tx_handler.block_disconnected(height, broadcaster, &bounded_fee_estimator, logger); self.best_block = BestBlock::new(header.prev_blockhash, height - 1); } @@ -2660,7 +2693,7 @@ impl ChannelMonitorImpl { &mut self, txid: &Txid, broadcaster: B, - fee_estimator: F, + fee_estimator: &LowerBoundedFeeEstimator, logger: L, ) where B::Target: BroadcasterInterface, @@ -2701,14 +2734,21 @@ impl ChannelMonitorImpl { if *idx == input.previous_output.vout { #[cfg(test)] { - // If the expected script is a known type, check that the witness - // appears to be spending the correct type (ie that the match would - // actually succeed in BIP 158/159-style filters). - if _script_pubkey.is_v0_p2wsh() { - assert_eq!(&bitcoin::Address::p2wsh(&Script::from(input.witness.last().unwrap().to_vec()), bitcoin::Network::Bitcoin).script_pubkey(), _script_pubkey); - } else if _script_pubkey.is_v0_p2wpkh() { - assert_eq!(&bitcoin::Address::p2wpkh(&bitcoin::PublicKey::from_slice(&input.witness.last().unwrap()).unwrap(), bitcoin::Network::Bitcoin).unwrap().script_pubkey(), _script_pubkey); - } else { panic!(); } + // If the expected script is a known type, check that the witness + // appears to be spending the correct type (ie that the match would + // actually succeed in BIP 158/159-style filters). + if _script_pubkey.is_v0_p2wsh() { + if input.witness.last().unwrap().to_vec() == deliberately_bogus_accepted_htlc_witness_program() { + // In at least one test we use a deliberately bogus witness + // script which hit an old panic. Thus, we check for that here + // and avoid the assert if its the expected bogus script. + return true; + } + + assert_eq!(&bitcoin::Address::p2wsh(&Script::from(input.witness.last().unwrap().to_vec()), bitcoin::Network::Bitcoin).script_pubkey(), _script_pubkey); + } else if _script_pubkey.is_v0_p2wpkh() { + assert_eq!(&bitcoin::Address::p2wpkh(&bitcoin::PublicKey::from_slice(&input.witness.last().unwrap()).unwrap(), bitcoin::Network::Bitcoin).unwrap().script_pubkey(), _script_pubkey); + } else { panic!(); } } return true; } @@ -2793,10 +2833,13 @@ impl ChannelMonitorImpl { let prev_last_witness_len = input.witness.second_to_last().map(|w| w.len()).unwrap_or(0); let revocation_sig_claim = (witness_items == 3 && htlctype == Some(HTLCType::OfferedHTLC) && prev_last_witness_len == 33) || (witness_items == 3 && htlctype == Some(HTLCType::AcceptedHTLC) && prev_last_witness_len == 33); - let accepted_preimage_claim = witness_items == 5 && htlctype == Some(HTLCType::AcceptedHTLC); + let accepted_preimage_claim = witness_items == 5 && htlctype == Some(HTLCType::AcceptedHTLC) + && input.witness.second_to_last().unwrap().len() == 32; #[cfg(not(fuzzing))] let accepted_timeout_claim = witness_items == 3 && htlctype == Some(HTLCType::AcceptedHTLC) && !revocation_sig_claim; - let offered_preimage_claim = witness_items == 3 && htlctype == Some(HTLCType::OfferedHTLC) && !revocation_sig_claim; + let offered_preimage_claim = witness_items == 3 && htlctype == Some(HTLCType::OfferedHTLC) && + !revocation_sig_claim && input.witness.second_to_last().unwrap().len() == 32; + #[cfg(not(fuzzing))] let offered_timeout_claim = witness_items == 5 && htlctype == Some(HTLCType::OfferedHTLC); @@ -3306,11 +3349,13 @@ impl<'a, Signer: Sign, K: KeysInterface> ReadableArgs<&'a K> let mut funding_spend_confirmed = None; let mut htlcs_resolved_on_chain = Some(Vec::new()); let mut funding_spend_seen = Some(false); + let mut counterparty_node_id = None; read_tlv_fields!(reader, { (1, funding_spend_confirmed, option), (3, htlcs_resolved_on_chain, vec_type), (5, pending_monitor_events, vec_type), (7, funding_spend_seen, option), + (9, counterparty_node_id, option), }); let mut secp_ctx = Secp256k1::new(); @@ -3365,6 +3410,7 @@ impl<'a, Signer: Sign, K: KeysInterface> ReadableArgs<&'a K> htlcs_resolved_on_chain: htlcs_resolved_on_chain.unwrap(), best_block, + counterparty_node_id, secp_ctx, }), @@ -3390,6 +3436,8 @@ mod tests { use hex; + use crate::chain::chaininterface::LowerBoundedFeeEstimator; + use super::ChannelMonitorUpdateStep; use ::{check_added_monitors, check_closed_broadcast, check_closed_event, check_spends, get_local_commitment_txn, get_monitor, get_route_and_payment_hash, unwrap_send_err}; use chain::{BestBlock, Confirm}; @@ -3511,7 +3559,7 @@ mod tests { let secp_ctx = Secp256k1::new(); let logger = Arc::new(TestLogger::new()); let broadcaster = Arc::new(TestBroadcaster{txn_broadcasted: Mutex::new(Vec::new()), blocks: Arc::new(Mutex::new(Vec::new()))}); - let fee_estimator = Arc::new(TestFeeEstimator { sat_per_kw: Mutex::new(253) }); + let fee_estimator = TestFeeEstimator { sat_per_kw: Mutex::new(253) }; let dummy_key = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); let dummy_tx = Transaction { version: 0, lock_time: 0, input: Vec::new(), output: Vec::new() }; @@ -3601,7 +3649,7 @@ mod tests { (OutPoint { txid: Txid::from_slice(&[43; 32]).unwrap(), index: 0 }, Script::new()), &channel_parameters, Script::new(), 46, 0, - HolderCommitmentTransaction::dummy(), best_block); + HolderCommitmentTransaction::dummy(), best_block, dummy_key); monitor.provide_latest_holder_commitment_tx(HolderCommitmentTransaction::dummy(), preimages_to_holder_htlcs!(preimages[0..10])).unwrap(); let dummy_txid = dummy_tx.txid(); @@ -3610,7 +3658,8 @@ mod tests { monitor.provide_latest_counterparty_commitment_tx(dummy_txid, preimages_slice_to_htlc_outputs!(preimages[17..20]), 281474976710653, dummy_key, &logger); monitor.provide_latest_counterparty_commitment_tx(dummy_txid, preimages_slice_to_htlc_outputs!(preimages[18..20]), 281474976710652, dummy_key, &logger); for &(ref preimage, ref hash) in preimages.iter() { - monitor.provide_payment_preimage(hash, preimage, &broadcaster, &fee_estimator, &logger); + let bounded_fee_estimator = LowerBoundedFeeEstimator::new(&fee_estimator); + monitor.provide_payment_preimage(hash, preimage, &broadcaster, &bounded_fee_estimator, &logger); } // Now provide a secret, pruning preimages 10-15