|
7 | 7 | // You may not use this file except in accordance with one or both of these
|
8 | 8 | // licenses.
|
9 | 9 |
|
10 |
| -use bitcoin::blockdata::block::BlockHeader; |
11 | 10 | use bitcoin::blockdata::script::{Script,Builder};
|
12 | 11 | use bitcoin::blockdata::transaction::{TxIn, TxOut, Transaction, SigHashType};
|
13 | 12 | use bitcoin::blockdata::opcodes;
|
@@ -3502,47 +3501,63 @@ impl<Signer: Sign> Channel<Signer> {
|
3502 | 3501 | self.network_sync == UpdateStatus::DisabledMarked
|
3503 | 3502 | }
|
3504 | 3503 |
|
3505 |
| - pub fn transactions_confirmed(&mut self, block_hash: &BlockHash, height: u32, txdata: &TransactionData) -> Result<(), msgs::ErrorMessage> { |
| 3504 | + /// When a transaction is confirmed, we check whether it is or spends the funding transaction |
| 3505 | + /// In the first case, we store the confirmation height and calculating the short channel id. |
| 3506 | + /// In the second, we simply return an Err indicating we need to be force-closed now. |
| 3507 | + pub fn transactions_confirmed<L: Deref>(&mut self, block_hash: &BlockHash, height: u32, txdata: &TransactionData, logger: &L) |
| 3508 | + -> Result<(), msgs::ErrorMessage> where L::Target: Logger { |
3506 | 3509 | let non_shutdown_state = self.channel_state & (!MULTI_STATE_FLAGS);
|
3507 |
| - if non_shutdown_state & !(ChannelState::TheirFundingLocked as u32) == ChannelState::FundingSent as u32 { |
3508 |
| - for &(index_in_block, tx) in txdata.iter() { |
3509 |
| - let funding_txo = self.get_funding_txo().unwrap(); |
3510 |
| - if tx.txid() == funding_txo.txid { |
3511 |
| - let txo_idx = funding_txo.index as usize; |
3512 |
| - if txo_idx >= tx.output.len() || tx.output[txo_idx].script_pubkey != self.get_funding_redeemscript().to_v0_p2wsh() || |
3513 |
| - tx.output[txo_idx].value != self.channel_value_satoshis { |
3514 |
| - if self.is_outbound() { |
3515 |
| - // If we generated the funding transaction and it doesn't match what it |
3516 |
| - // should, the client is really broken and we should just panic and |
3517 |
| - // tell them off. That said, because hash collisions happen with high |
3518 |
| - // probability in fuzztarget mode, if we're fuzzing we just close the |
3519 |
| - // channel and move on. |
3520 |
| - #[cfg(not(feature = "fuzztarget"))] |
3521 |
| - panic!("Client called ChannelManager::funding_transaction_generated with bogus transaction!"); |
| 3510 | + for &(index_in_block, tx) in txdata.iter() { |
| 3511 | + if let Some(funding_txo) = self.get_funding_txo() { |
| 3512 | + // If we haven't yet sent a funding_locked, but are in FundingSent (ignoring |
| 3513 | + // whether they've sent a funding_locked or not), check if we should send one. |
| 3514 | + if non_shutdown_state & !(ChannelState::TheirFundingLocked as u32) == ChannelState::FundingSent as u32 { |
| 3515 | + if tx.txid() == funding_txo.txid { |
| 3516 | + let txo_idx = funding_txo.index as usize; |
| 3517 | + if txo_idx >= tx.output.len() || tx.output[txo_idx].script_pubkey != self.get_funding_redeemscript().to_v0_p2wsh() || |
| 3518 | + tx.output[txo_idx].value != self.channel_value_satoshis { |
| 3519 | + if self.is_outbound() { |
| 3520 | + // If we generated the funding transaction and it doesn't match what it |
| 3521 | + // should, the client is really broken and we should just panic and |
| 3522 | + // tell them off. That said, because hash collisions happen with high |
| 3523 | + // probability in fuzztarget mode, if we're fuzzing we just close the |
| 3524 | + // channel and move on. |
| 3525 | + #[cfg(not(feature = "fuzztarget"))] |
| 3526 | + panic!("Client called ChannelManager::funding_transaction_generated with bogus transaction!"); |
| 3527 | + } |
| 3528 | + self.channel_state = ChannelState::ShutdownComplete as u32; |
| 3529 | + self.update_time_counter += 1; |
| 3530 | + return Err(msgs::ErrorMessage { |
| 3531 | + channel_id: self.channel_id(), |
| 3532 | + data: "funding tx had wrong script/value or output index".to_owned() |
| 3533 | + }); |
| 3534 | + } else { |
| 3535 | + if self.is_outbound() { |
| 3536 | + for input in tx.input.iter() { |
| 3537 | + if input.witness.is_empty() { |
| 3538 | + // We generated a malleable funding transaction, implying we've |
| 3539 | + // just exposed ourselves to funds loss to our counterparty. |
| 3540 | + #[cfg(not(feature = "fuzztarget"))] |
| 3541 | + panic!("Client called ChannelManager::funding_transaction_generated with bogus transaction!"); |
| 3542 | + } |
| 3543 | + } |
| 3544 | + } |
| 3545 | + self.funding_tx_confirmation_height = height as u64; |
| 3546 | + self.funding_tx_confirmed_in = Some(*block_hash); |
| 3547 | + self.short_channel_id = match scid_from_parts(height as u64, index_in_block as u64, txo_idx as u64) { |
| 3548 | + Ok(scid) => Some(scid), |
| 3549 | + Err(_) => panic!("Block was bogus - either height was > 16 million, had > 16 million transactions, or had > 65k outputs"), |
| 3550 | + } |
3522 | 3551 | }
|
3523 |
| - self.channel_state = ChannelState::ShutdownComplete as u32; |
3524 |
| - self.update_time_counter += 1; |
| 3552 | + } |
| 3553 | + } |
| 3554 | + for inp in tx.input.iter() { |
| 3555 | + if inp.previous_output == funding_txo.into_bitcoin_outpoint() { |
| 3556 | + log_trace!(logger, "Detected channel-closing tx {} spending {}:{}, closing channel {}", tx.txid(), inp.previous_output.txid, inp.previous_output.vout, log_bytes!(self.channel_id())); |
3525 | 3557 | return Err(msgs::ErrorMessage {
|
3526 | 3558 | channel_id: self.channel_id(),
|
3527 |
| - data: "funding tx had wrong script/value".to_owned() |
| 3559 | + data: "Commitment or closing transaction was confirmed on chain.".to_owned() |
3528 | 3560 | });
|
3529 |
| - } else { |
3530 |
| - if self.is_outbound() { |
3531 |
| - for input in tx.input.iter() { |
3532 |
| - if input.witness.is_empty() { |
3533 |
| - // We generated a malleable funding transaction, implying we've |
3534 |
| - // just exposed ourselves to funds loss to our counterparty. |
3535 |
| - #[cfg(not(feature = "fuzztarget"))] |
3536 |
| - panic!("Client called ChannelManager::funding_transaction_generated with bogus transaction!"); |
3537 |
| - } |
3538 |
| - } |
3539 |
| - } |
3540 |
| - self.funding_tx_confirmation_height = height as u64; |
3541 |
| - self.funding_tx_confirmed_in = Some(*block_hash); |
3542 |
| - self.short_channel_id = match scid_from_parts(height as u64, index_in_block as u64, txo_idx as u64) { |
3543 |
| - Ok(scid) => Some(scid), |
3544 |
| - Err(_) => panic!("Block was bogus - either height was > 16 million, had > 16 million transactions, or had > 65k outputs"), |
3545 |
| - } |
3546 | 3561 | }
|
3547 | 3562 | }
|
3548 | 3563 | }
|
@@ -3635,35 +3650,6 @@ impl<Signer: Sign> Channel<Signer> {
|
3635 | 3650 | Ok((None, timed_out_htlcs))
|
3636 | 3651 | }
|
3637 | 3652 |
|
3638 |
| - /// When we receive a new block, we (a) check whether the block contains the funding |
3639 |
| - /// transaction (which would start us counting blocks until we send the funding_signed), and |
3640 |
| - /// (b) check the height of the block against outbound holding cell HTLCs in case we need to |
3641 |
| - /// give up on them prematurely and time them out. Everything else (e.g. commitment |
3642 |
| - /// transaction broadcasts, channel closure detection, HTLC transaction broadcasting, etc) is |
3643 |
| - /// handled by the ChannelMonitor. |
3644 |
| - /// |
3645 |
| - /// If we return Err, the channel may have been closed, at which point the standard |
3646 |
| - /// requirements apply - no calls may be made except those explicitly stated to be allowed |
3647 |
| - /// post-shutdown. |
3648 |
| - /// Only returns an ErrorAction of DisconnectPeer, if Err. |
3649 |
| - /// |
3650 |
| - /// May return some HTLCs (and their payment_hash) which have timed out and should be failed |
3651 |
| - /// back. |
3652 |
| - pub fn block_connected(&mut self, header: &BlockHeader, txdata: &TransactionData, height: u32) -> Result<(Option<msgs::FundingLocked>, Vec<(HTLCSource, PaymentHash)>), msgs::ErrorMessage> { |
3653 |
| - self.transactions_confirmed(&header.block_hash(), height, txdata)?; |
3654 |
| - self.update_best_block(height, header.time) |
3655 |
| - } |
3656 |
| - |
3657 |
| - /// Called by channelmanager based on chain blocks being disconnected. |
3658 |
| - /// Returns true if we need to close the channel now due to funding transaction |
3659 |
| - /// unconfirmation/reorg. |
3660 |
| - pub fn block_disconnected(&mut self, header: &BlockHeader, new_height: u32) -> bool { |
3661 |
| - if self.update_best_block(new_height, header.time).is_err() { |
3662 |
| - return true; |
3663 |
| - } |
3664 |
| - false |
3665 |
| - } |
3666 |
| - |
3667 | 3653 | // Methods to get unprompted messages to send to the remote end (or where we already returned
|
3668 | 3654 | // something in the handler for the message that prompted this message):
|
3669 | 3655 |
|
|
0 commit comments