From 31093adef83223494f4fc93c26d91d4bc365bdba Mon Sep 17 00:00:00 2001 From: Jeffrey Czyz Date: Thu, 4 Mar 2021 18:22:37 -0800 Subject: [PATCH] Pass along ChannelManager's last_block_hash ChannelMonitor keeps track of the last block connected. However, it is initialized with the default block hash, which is a problem if the ChannelMonitor is serialized before a block is connected. Instead, pass ChannelManager's last_block_hash, which is initialized with a "birthday" hash, when creating a new ChannelMonitor. --- lightning/src/chain/channelmonitor.rs | 10 +++++++--- lightning/src/ln/channel.rs | 16 +++++++++------- lightning/src/ln/channelmanager.rs | 6 ++++-- 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/lightning/src/chain/channelmonitor.rs b/lightning/src/chain/channelmonitor.rs index 0c23a1ef..8a8a5b96 100644 --- a/lightning/src/chain/channelmonitor.rs +++ b/lightning/src/chain/channelmonitor.rs @@ -980,7 +980,8 @@ impl ChannelMonitor { channel_parameters: &ChannelTransactionParameters, funding_redeemscript: Script, channel_value_satoshis: u64, commitment_transaction_number_obscure_factor: u64, - initial_holder_commitment_tx: HolderCommitmentTransaction) -> ChannelMonitor { + initial_holder_commitment_tx: HolderCommitmentTransaction, + last_block_hash: BlockHash) -> ChannelMonitor { assert!(commitment_transaction_number_obscure_factor <= (1 << 48)); let our_channel_close_key_hash = WPubkeyHash::hash(&shutdown_pubkey.serialize()); @@ -1067,7 +1068,7 @@ impl ChannelMonitor { lockdown_from_offchain: false, holder_tx_signed: false, - last_block_hash: Default::default(), + last_block_hash, secp_ctx, }), } @@ -2789,6 +2790,7 @@ impl<'a, Signer: Sign, K: KeysInterface> ReadableArgs<&'a K> #[cfg(test)] mod tests { + use bitcoin::blockdata::constants::genesis_block; use bitcoin::blockdata::script::{Script, Builder}; use bitcoin::blockdata::opcodes; use bitcoin::blockdata::transaction::{Transaction, TxIn, TxOut, SigHashType}; @@ -2798,6 +2800,7 @@ mod tests { use bitcoin::hashes::sha256::Hash as Sha256; use bitcoin::hashes::hex::FromHex; use bitcoin::hash_types::Txid; + use bitcoin::network::constants::Network; use hex; use chain::channelmonitor::ChannelMonitor; use chain::transaction::OutPoint; @@ -2897,12 +2900,13 @@ mod tests { }; // Prune with one old state and a holder commitment tx holding a few overlaps with the // old state. + let last_block_hash = genesis_block(Network::Testnet).block_hash(); let monitor = ChannelMonitor::new(Secp256k1::new(), keys, &PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()), 0, &Script::new(), (OutPoint { txid: Txid::from_slice(&[43; 32]).unwrap(), index: 0 }, Script::new()), &channel_parameters, Script::new(), 46, 0, - HolderCommitmentTransaction::dummy()); + HolderCommitmentTransaction::dummy(), last_block_hash); monitor.provide_latest_holder_commitment_tx(HolderCommitmentTransaction::dummy(), preimages_to_holder_htlcs!(preimages[0..10])).unwrap(); let dummy_txid = dummy_tx.txid(); diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index 0158448d..9e4bb081 100644 --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@ -1516,7 +1516,7 @@ impl Channel { &self.get_counterparty_pubkeys().funding_pubkey } - pub fn funding_created(&mut self, msg: &msgs::FundingCreated, logger: &L) -> Result<(msgs::FundingSigned, ChannelMonitor), ChannelError> where L::Target: Logger { + pub fn funding_created(&mut self, msg: &msgs::FundingCreated, last_block_hash: BlockHash, logger: &L) -> Result<(msgs::FundingSigned, ChannelMonitor), ChannelError> where L::Target: Logger { if self.is_outbound() { return Err(ChannelError::Close("Received funding_created for an outbound channel?".to_owned())); } @@ -1570,7 +1570,7 @@ impl Channel { &self.channel_transaction_parameters, funding_redeemscript.clone(), self.channel_value_satoshis, obscure_factor, - holder_commitment_tx); + holder_commitment_tx, last_block_hash); channel_monitor.provide_latest_counterparty_commitment_tx(counterparty_initial_commitment_txid, Vec::new(), self.cur_counterparty_commitment_transaction_number, self.counterparty_cur_commitment_point.unwrap(), logger); @@ -1587,7 +1587,7 @@ impl Channel { /// Handles a funding_signed message from the remote end. /// If this call is successful, broadcast the funding transaction (and not before!) - pub fn funding_signed(&mut self, msg: &msgs::FundingSigned, logger: &L) -> Result, ChannelError> where L::Target: Logger { + pub fn funding_signed(&mut self, msg: &msgs::FundingSigned, last_block_hash: BlockHash, logger: &L) -> Result, ChannelError> where L::Target: Logger { if !self.is_outbound() { return Err(ChannelError::Close("Received funding_signed for an inbound channel?".to_owned())); } @@ -1640,7 +1640,7 @@ impl Channel { &self.channel_transaction_parameters, funding_redeemscript.clone(), self.channel_value_satoshis, obscure_factor, - holder_commitment_tx); + holder_commitment_tx, last_block_hash); channel_monitor.provide_latest_counterparty_commitment_tx(counterparty_initial_bitcoin_tx.txid, Vec::new(), self.cur_counterparty_commitment_transaction_number, self.counterparty_cur_commitment_point.unwrap(), logger); @@ -4910,6 +4910,8 @@ mod tests { let secp_ctx = Secp256k1::new(); let seed = [42; 32]; let network = Network::Testnet; + let chain_hash = genesis_block(network).header.block_hash(); + let last_block_hash = chain_hash; let keys_provider = test_utils::TestKeysInterface::new(&seed, network); // Go through the flow of opening a channel between two nodes. @@ -4920,7 +4922,7 @@ mod tests { let mut node_a_chan = Channel::::new_outbound(&&feeest, &&keys_provider, node_b_node_id, 10000000, 100000, 42, &config).unwrap(); // Create Node B's channel by receiving Node A's open_channel message - let open_channel_msg = node_a_chan.get_open_channel(genesis_block(network).header.block_hash()); + let open_channel_msg = node_a_chan.get_open_channel(chain_hash); let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[7; 32]).unwrap()); let mut node_b_chan = Channel::::new_from_req(&&feeest, &&keys_provider, node_b_node_id, InitFeatures::known(), &open_channel_msg, 7, &config).unwrap(); @@ -4935,10 +4937,10 @@ mod tests { }]}; let funding_outpoint = OutPoint{ txid: tx.txid(), index: 0 }; let funding_created_msg = node_a_chan.get_outbound_funding_created(funding_outpoint, &&logger).unwrap(); - let (funding_signed_msg, _) = node_b_chan.funding_created(&funding_created_msg, &&logger).unwrap(); + let (funding_signed_msg, _) = node_b_chan.funding_created(&funding_created_msg, last_block_hash, &&logger).unwrap(); // Node B --> Node A: funding signed - let _ = node_a_chan.funding_signed(&funding_signed_msg, &&logger); + let _ = node_a_chan.funding_signed(&funding_signed_msg, last_block_hash, &&logger); // Now disconnect the two nodes and check that the commitment point in // Node B's channel_reestablish message is sane. diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index 24d7c453..b356641a 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -2461,7 +2461,8 @@ impl ChannelMana if chan.get().get_counterparty_node_id() != *counterparty_node_id { return Err(MsgHandleErrInternal::send_err_msg_no_close("Got a message for a channel from the wrong node!".to_owned(), msg.temporary_channel_id)); } - (try_chan_entry!(self, chan.get_mut().funding_created(msg, &self.logger), channel_state, chan), chan.remove()) + let last_block_hash = *self.last_block_hash.lock().unwrap(); + (try_chan_entry!(self, chan.get_mut().funding_created(msg, last_block_hash, &self.logger), channel_state, chan), chan.remove()) }, hash_map::Entry::Vacant(_) => return Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel".to_owned(), msg.temporary_channel_id)) } @@ -2517,7 +2518,8 @@ impl ChannelMana if chan.get().get_counterparty_node_id() != *counterparty_node_id { return Err(MsgHandleErrInternal::send_err_msg_no_close("Got a message for a channel from the wrong node!".to_owned(), msg.channel_id)); } - let monitor = match chan.get_mut().funding_signed(&msg, &self.logger) { + let last_block_hash = *self.last_block_hash.lock().unwrap(); + let monitor = match chan.get_mut().funding_signed(&msg, last_block_hash, &self.logger) { Ok(update) => update, Err(e) => try_chan_entry!(self, Err(e), channel_state, chan), }; -- 2.30.2