X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fchain%2Fchannelmonitor.rs;h=6daab991922f160be0d4062f5cb392545f69789e;hb=b5902fecd40574fe4017a5b173fd2576b0d595f9;hp=91544f11334e4eb5bcf4683da632262cfd7dce82;hpb=040bf2284eeb01e23bdd53ad43d663f1e6dba22a;p=rust-lightning diff --git a/lightning/src/chain/channelmonitor.rs b/lightning/src/chain/channelmonitor.rs index 91544f11..6daab991 100644 --- a/lightning/src/chain/channelmonitor.rs +++ b/lightning/src/chain/channelmonitor.rs @@ -20,7 +20,7 @@ //! security-domain-separated system design, you should consider having multiple paths for //! ChannelMonitors to get out of the HSM and onto monitoring devices. -use bitcoin::blockdata::block::{Block, BlockHeader}; +use bitcoin::blockdata::block::BlockHeader; use bitcoin::blockdata::transaction::{TxOut,Transaction}; use bitcoin::blockdata::script::{Script, Builder}; use bitcoin::blockdata::opcodes; @@ -29,8 +29,8 @@ use bitcoin::hashes::Hash; use bitcoin::hashes::sha256::Hash as Sha256; use bitcoin::hash_types::{Txid, BlockHash, WPubkeyHash}; -use bitcoin::secp256k1::{Secp256k1,Signature}; -use bitcoin::secp256k1::key::{SecretKey,PublicKey}; +use bitcoin::secp256k1::{Secp256k1, ecdsa::Signature}; +use bitcoin::secp256k1::{SecretKey, PublicKey}; use bitcoin::secp256k1; use ln::{PaymentHash, PaymentPreimage}; @@ -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; @@ -166,11 +166,11 @@ pub struct HTLCUpdate { pub(crate) payment_hash: PaymentHash, pub(crate) payment_preimage: Option, pub(crate) source: HTLCSource, - pub(crate) onchain_value_satoshis: Option, + pub(crate) htlc_value_satoshis: Option, } impl_writeable_tlv_based!(HTLCUpdate, { (0, payment_hash, required), - (1, onchain_value_satoshis, option), + (1, htlc_value_satoshis, option), (2, source, required), (4, payment_preimage, option), }); @@ -256,7 +256,7 @@ impl_writeable_tlv_based!(HolderSignedTx, { /// We use this to track static counterparty commitment transaction data and to generate any /// justice or 2nd-stage preimage/timeout transactions. -#[derive(PartialEq)] +#[derive(Clone, PartialEq)] struct CounterpartyCommitmentParameters { counterparty_delayed_payment_base_key: PublicKey, counterparty_htlc_base_key: PublicKey, @@ -310,7 +310,7 @@ impl Readable for CounterpartyCommitmentParameters { /// transaction causing it. /// /// Used to determine when the on-chain event can be considered safe from a chain reorganization. -#[derive(PartialEq)] +#[derive(Clone, PartialEq)] struct OnchainEventEntry { txid: Txid, height: u32, @@ -346,7 +346,7 @@ impl OnchainEventEntry { /// Upon discovering of some classes of onchain tx by ChannelMonitor, we may have to take actions on it /// once they mature to enough confirmations (ANTI_REORG_DELAY) -#[derive(PartialEq)] +#[derive(Clone, PartialEq)] enum OnchainEvent { /// An outbound HTLC failing after a transaction is confirmed. Used /// * when an outbound HTLC output is spent by us after the HTLC timed out @@ -357,10 +357,10 @@ enum OnchainEvent { HTLCUpdate { source: HTLCSource, payment_hash: PaymentHash, - onchain_value_satoshis: Option, + htlc_value_satoshis: Option, /// None in the second case, above, ie when there is no relevant output in the commitment /// transaction which appeared on chain. - input_idx: Option, + commitment_tx_output_idx: Option, }, MaturingOutput { descriptor: SpendableOutputDescriptor, @@ -381,7 +381,7 @@ enum OnchainEvent { /// * a revoked-state HTLC transaction was broadcasted, which was claimed by the revocation /// signature. HTLCSpendConfirmation { - input_idx: u32, + commitment_tx_output_idx: u32, /// If the claim was made by either party with a preimage, this is filled in preimage: Option, /// If the claim was made by us on an inbound HTLC against a local commitment transaction, @@ -423,9 +423,9 @@ impl MaybeReadable for OnchainEventEntry { impl_writeable_tlv_based_enum_upgradable!(OnchainEvent, (0, HTLCUpdate) => { (0, source, required), - (1, onchain_value_satoshis, option), + (1, htlc_value_satoshis, option), (2, payment_hash, required), - (3, input_idx, option), + (3, commitment_tx_output_idx, option), }, (1, MaturingOutput) => { (0, descriptor, required), @@ -434,7 +434,7 @@ impl_writeable_tlv_based_enum_upgradable!(OnchainEvent, (0, on_local_output_csv, option), }, (5, HTLCSpendConfirmation) => { - (0, input_idx, required), + (0, commitment_tx_output_idx, required), (2, preimage, option), (4, on_to_local_output_csv, option), }, @@ -452,7 +452,7 @@ pub(crate) enum ChannelMonitorUpdateStep { commitment_txid: Txid, htlc_outputs: Vec<(HTLCOutputInCommitment, Option>)>, commitment_number: u64, - their_revocation_point: PublicKey, + their_per_commitment_point: PublicKey, }, PaymentPreimage { payment_preimage: PaymentPreimage, @@ -494,7 +494,7 @@ impl_writeable_tlv_based_enum_upgradable!(ChannelMonitorUpdateStep, (1, LatestCounterpartyCommitmentTXInfo) => { (0, commitment_txid, required), (2, commitment_number, required), - (4, their_revocation_point, required), + (4, their_per_commitment_point, required), (6, htlc_outputs, vec_type), }, (2, PaymentPreimage) => { @@ -566,15 +566,15 @@ pub enum Balance { } /// An HTLC which has been irrevocably resolved on-chain, and has reached ANTI_REORG_DELAY. -#[derive(PartialEq)] +#[derive(Clone, PartialEq)] struct IrrevocablyResolvedHTLC { - input_idx: u32, + commitment_tx_output_idx: u32, /// Only set if the HTLC claim was ours using a payment preimage payment_preimage: Option, } impl_writeable_tlv_based!(IrrevocablyResolvedHTLC, { - (0, input_idx, required), + (0, commitment_tx_output_idx, required), (2, payment_preimage, option), }); @@ -601,6 +601,13 @@ pub struct ChannelMonitor { inner: Mutex>, } +impl Clone for ChannelMonitor { + fn clone(&self) -> Self { + Self { inner: Mutex::new(self.inner.lock().unwrap().clone()) } + } +} + +#[derive(Clone)] pub(crate) struct ChannelMonitorImpl { latest_update_id: u64, commitment_transaction_number_obscure_factor: u64, @@ -619,8 +626,8 @@ pub(crate) struct ChannelMonitorImpl { counterparty_commitment_params: CounterpartyCommitmentParameters, funding_redeemscript: Script, channel_value_satoshis: u64, - // first is the idx of the first of the two revocation points - their_cur_revocation_points: Option<(u64, PublicKey, Option)>, + // first is the idx of the first of the two per-commitment points + their_cur_per_commitment_points: Option<(u64, PublicKey, Option)>, on_holder_tx_csv: u16, @@ -655,6 +662,10 @@ pub(crate) struct ChannelMonitorImpl { // deserialization current_holder_commitment_number: u64, + /// The set of payment hashes from inbound payments for which we know the preimage. Payment + /// preimages that are not included in any unrevoked local commitment transaction or unrevoked + /// remote commitment transactions are automatically removed when commitment transactions are + /// revoked. payment_preimages: HashMap, // Note that `MonitorEvent`s MUST NOT be generated during update processing, only generated @@ -718,6 +729,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... } @@ -753,7 +767,7 @@ impl PartialEq for ChannelMonitorImpl { self.counterparty_commitment_params != other.counterparty_commitment_params || self.funding_redeemscript != other.funding_redeemscript || self.channel_value_satoshis != other.channel_value_satoshis || - self.their_cur_revocation_points != other.their_cur_revocation_points || + self.their_cur_per_commitment_points != other.their_cur_per_commitment_points || self.on_holder_tx_csv != other.on_holder_tx_csv || self.commitment_secrets != other.commitment_secrets || self.counterparty_claimable_outpoints != other.counterparty_claimable_outpoints || @@ -828,7 +842,7 @@ impl Writeable for ChannelMonitorImpl { self.funding_redeemscript.write(writer)?; self.channel_value_satoshis.write(writer)?; - match self.their_cur_revocation_points { + match self.their_cur_per_commitment_points { Some((idx, pubkey, second_option)) => { writer.write_all(&byte_utils::be48_to_array(idx))?; writer.write_all(&pubkey.serialize())?; @@ -865,6 +879,9 @@ impl Writeable for ChannelMonitorImpl { writer.write_all(&txid[..])?; writer.write_all(&byte_utils::be64_to_array(htlc_infos.len() as u64))?; for &(ref htlc_output, ref htlc_source) in htlc_infos.iter() { + debug_assert!(htlc_source.is_none() || Some(**txid) == self.current_counterparty_commitment_txid + || Some(**txid) == self.prev_counterparty_commitment_txid, + "HTLC Sources for all revoked commitment transactions should be none!"); serialize_htlc_in_commitment!(htlc_output); htlc_source.as_ref().map(|b| b.as_ref()).write(writer)?; } @@ -947,6 +964,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(()) @@ -954,13 +972,20 @@ impl Writeable for ChannelMonitorImpl { } impl ChannelMonitor { + /// For lockorder enforcement purposes, we need to have a single site which constructs the + /// `inner` mutex, otherwise cases where we lock two monitors at the same time (eg in our + /// PartialEq implementation) we may decide a lockorder violation has occurred. + fn from_impl(imp: ChannelMonitorImpl) -> Self { + ChannelMonitor { inner: Mutex::new(imp) } + } + pub(crate) fn new(secp_ctx: Secp256k1, keys: Signer, shutdown_script: Option