From: valentinewallace Date: Mon, 10 Jun 2024 22:30:09 +0000 (-0400) Subject: Merge pull request #3086 from alecchendev/2024-05-holder-commitment X-Git-Tag: v0.0.124-beta~89 X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=commitdiff_plain;h=f2237a78ff032e5113f5b44edb415b6bd12ebfab;hp=-c;p=rust-lightning Merge pull request #3086 from alecchendev/2024-05-holder-commitment Add `HolderCommitmentPoint` struct to track commitment points --- f2237a78ff032e5113f5b44edb415b6bd12ebfab diff --combined lightning/src/ln/channel.rs index 716eba7cf,b830f9f31..d6ab1876a --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@@ -7,7 -7,6 +7,7 @@@ // You may not use this file except in accordance with one or both of these // licenses. +use bitcoin::amount::Amount; use bitcoin::blockdata::constants::ChainHash; use bitcoin::blockdata::script::{Script, ScriptBuf, Builder}; use bitcoin::blockdata::transaction::Transaction; @@@ -30,8 -29,7 +30,8 @@@ use crate::ln::features::{ChannelTypeFe use crate::ln::msgs; use crate::ln::msgs::DecodeError; use crate::ln::script::{self, ShutdownScript}; -use crate::ln::channelmanager::{self, CounterpartyForwardingInfo, PendingHTLCStatus, HTLCSource, SentHTLCId, HTLCFailureMsg, PendingHTLCInfo, RAACommitmentOrder, BREAKDOWN_TIMEOUT, MIN_CLTV_EXPIRY_DELTA, MAX_LOCAL_BREAKDOWN_TIMEOUT, ChannelShutdownState}; +use crate::ln::channel_state::{ChannelShutdownState, CounterpartyForwardingInfo, InboundHTLCDetails, InboundHTLCStateDetails, OutboundHTLCDetails, OutboundHTLCStateDetails}; +use crate::ln::channelmanager::{self, PendingHTLCStatus, HTLCSource, SentHTLCId, HTLCFailureMsg, PendingHTLCInfo, RAACommitmentOrder, BREAKDOWN_TIMEOUT, MIN_CLTV_EXPIRY_DELTA, MAX_LOCAL_BREAKDOWN_TIMEOUT}; use crate::ln::chan_utils::{CounterpartyCommitmentSecrets, TxCreationKeys, HTLCOutputInCommitment, htlc_success_tx_weight, htlc_timeout_tx_weight, make_funding_redeemscript, ChannelPublicKeys, CommitmentTransaction, HolderCommitmentTransaction, ChannelTransactionParameters, CounterpartyChannelTransactionParameters, MAX_HTLCS, get_commitment_transaction_number_obscure_factor, ClosingTransaction}; use crate::ln::chan_utils; use crate::ln::onion_utils::HTLCFailReason; @@@ -187,6 -185,45 +187,6 @@@ enum InboundHTLCState LocalRemoved(InboundHTLCRemovalReason), } -/// Exposes the state of pending inbound HTLCs. -/// -/// At a high level, an HTLC being forwarded from one Lightning node to another Lightning node goes -/// through the following states in the state machine: -/// - Announced for addition by the originating node through the update_add_htlc message. -/// - Added to the commitment transaction of the receiving node and originating node in turn -/// through the exchange of commitment_signed and revoke_and_ack messages. -/// - Announced for resolution (fulfillment or failure) by the receiving node through either one of -/// the update_fulfill_htlc, update_fail_htlc, and update_fail_malformed_htlc messages. -/// - Removed from the commitment transaction of the originating node and receiving node in turn -/// through the exchange of commitment_signed and revoke_and_ack messages. -/// -/// This can be used to inspect what next message an HTLC is waiting for to advance its state. -#[derive(Clone, Debug, PartialEq)] -pub enum InboundHTLCStateDetails { - /// We have added this HTLC in our commitment transaction by receiving commitment_signed and - /// returning revoke_and_ack. We are awaiting the appropriate revoke_and_ack's from the remote - /// before this HTLC is included on the remote commitment transaction. - AwaitingRemoteRevokeToAdd, - /// This HTLC has been included in the commitment_signed and revoke_and_ack messages on both sides - /// and is included in both commitment transactions. - /// - /// This HTLC is now safe to either forward or be claimed as a payment by us. The HTLC will - /// remain in this state until the forwarded upstream HTLC has been resolved and we resolve this - /// HTLC correspondingly, or until we claim it as a payment. If it is part of a multipart - /// payment, it will only be claimed together with other required parts. - Committed, - /// We have received the preimage for this HTLC and it is being removed by fulfilling it with - /// update_fulfill_htlc. This HTLC is still on both commitment transactions, but we are awaiting - /// the appropriate revoke_and_ack's from the remote before this HTLC is removed from the remote - /// commitment transaction after update_fulfill_htlc. - AwaitingRemoteRevokeToRemoveFulfill, - /// The HTLC is being removed by failing it with update_fail_htlc or update_fail_malformed_htlc. - /// This HTLC is still on both commitment transactions, but we are awaiting the appropriate - /// revoke_and_ack's from the remote before this HTLC is removed from the remote commitment - /// transaction. - AwaitingRemoteRevokeToRemoveFail, -} - impl From<&InboundHTLCState> for Option { fn from(state: &InboundHTLCState) -> Option { match state { @@@ -207,6 -244,13 +207,6 @@@ } } -impl_writeable_tlv_based_enum_upgradable!(InboundHTLCStateDetails, - (0, AwaitingRemoteRevokeToAdd) => {}, - (2, Committed) => {}, - (4, AwaitingRemoteRevokeToRemoveFulfill) => {}, - (6, AwaitingRemoteRevokeToRemoveFail) => {}; -); - struct InboundHTLCOutput { htlc_id: u64, amount_msat: u64, @@@ -215,6 -259,53 +215,6 @@@ state: InboundHTLCState, } -/// Exposes details around pending inbound HTLCs. -#[derive(Clone, Debug, PartialEq)] -pub struct InboundHTLCDetails { - /// The HTLC ID. - /// The IDs are incremented by 1 starting from 0 for each offered HTLC. - /// They are unique per channel and inbound/outbound direction, unless an HTLC was only announced - /// and not part of any commitment transaction. - pub htlc_id: u64, - /// The amount in msat. - pub amount_msat: u64, - /// The block height at which this HTLC expires. - pub cltv_expiry: u32, - /// The payment hash. - pub payment_hash: PaymentHash, - /// The state of the HTLC in the state machine. - /// - /// Determines on which commitment transactions the HTLC is included and what message the HTLC is - /// waiting for to advance to the next state. - /// - /// See [`InboundHTLCStateDetails`] for information on the specific states. - /// - /// LDK will always fill this field in, but when downgrading to prior versions of LDK, new - /// states may result in `None` here. - pub state: Option, - /// Whether the HTLC has an output below the local dust limit. If so, the output will be trimmed - /// from the local commitment transaction and added to the commitment transaction fee. - /// For non-anchor channels, this takes into account the cost of the second-stage HTLC - /// transactions as well. - /// - /// When the local commitment transaction is broadcasted as part of a unilateral closure, - /// the value of this HTLC will therefore not be claimable but instead burned as a transaction - /// fee. - /// - /// Note that dust limits are specific to each party. An HTLC can be dust for the local - /// commitment transaction but not for the counterparty's commitment transaction and vice versa. - pub is_dust: bool, -} - -impl_writeable_tlv_based!(InboundHTLCDetails, { - (0, htlc_id, required), - (2, amount_msat, required), - (4, cltv_expiry, required), - (6, payment_hash, required), - (7, state, upgradable_option), - (8, is_dust, required), -}); - #[cfg_attr(test, derive(Clone, Debug, PartialEq))] enum OutboundHTLCState { /// Added by us and included in a commitment_signed (if we were AwaitingRemoteRevoke when we @@@ -248,6 -339,42 +248,6 @@@ AwaitingRemovedRemoteRevoke(OutboundHTLCOutcome), } -/// Exposes the state of pending outbound HTLCs. -/// -/// At a high level, an HTLC being forwarded from one Lightning node to another Lightning node goes -/// through the following states in the state machine: -/// - Announced for addition by the originating node through the update_add_htlc message. -/// - Added to the commitment transaction of the receiving node and originating node in turn -/// through the exchange of commitment_signed and revoke_and_ack messages. -/// - Announced for resolution (fulfillment or failure) by the receiving node through either one of -/// the update_fulfill_htlc, update_fail_htlc, and update_fail_malformed_htlc messages. -/// - Removed from the commitment transaction of the originating node and receiving node in turn -/// through the exchange of commitment_signed and revoke_and_ack messages. -/// -/// This can be used to inspect what next message an HTLC is waiting for to advance its state. -#[derive(Clone, Debug, PartialEq)] -pub enum OutboundHTLCStateDetails { - /// We are awaiting the appropriate revoke_and_ack's from the remote before the HTLC is added - /// on the remote's commitment transaction after update_add_htlc. - AwaitingRemoteRevokeToAdd, - /// The HTLC has been added to the remote's commitment transaction by sending commitment_signed - /// and receiving revoke_and_ack in return. - /// - /// The HTLC will remain in this state until the remote node resolves the HTLC, or until we - /// unilaterally close the channel due to a timeout with an uncooperative remote node. - Committed, - /// The HTLC has been fulfilled successfully by the remote with a preimage in update_fulfill_htlc, - /// and we removed the HTLC from our commitment transaction by receiving commitment_signed and - /// returning revoke_and_ack. We are awaiting the appropriate revoke_and_ack's from the remote - /// for the removal from its commitment transaction. - AwaitingRemoteRevokeToRemoveSuccess, - /// The HTLC has been failed by the remote with update_fail_htlc or update_fail_malformed_htlc, - /// and we removed the HTLC from our commitment transaction by receiving commitment_signed and - /// returning revoke_and_ack. We are awaiting the appropriate revoke_and_ack's from the remote - /// for the removal from its commitment transaction. - AwaitingRemoteRevokeToRemoveFailure, -} - impl From<&OutboundHTLCState> for OutboundHTLCStateDetails { fn from(state: &OutboundHTLCState) -> OutboundHTLCStateDetails { match state { @@@ -271,6 -398,13 +271,6 @@@ } } -impl_writeable_tlv_based_enum_upgradable!(OutboundHTLCStateDetails, - (0, AwaitingRemoteRevokeToAdd) => {}, - (2, Committed) => {}, - (4, AwaitingRemoteRevokeToRemoveSuccess) => {}, - (6, AwaitingRemoteRevokeToRemoveFailure) => {}; -); - #[derive(Clone)] #[cfg_attr(test, derive(Debug, PartialEq))] enum OutboundHTLCOutcome { @@@ -309,6 -443,58 +309,6 @@@ struct OutboundHTLCOutput skimmed_fee_msat: Option, } -/// Exposes details around pending outbound HTLCs. -#[derive(Clone, Debug, PartialEq)] -pub struct OutboundHTLCDetails { - /// The HTLC ID. - /// The IDs are incremented by 1 starting from 0 for each offered HTLC. - /// They are unique per channel and inbound/outbound direction, unless an HTLC was only announced - /// and not part of any commitment transaction. - /// - /// Not present when we are awaiting a remote revocation and the HTLC is not added yet. - pub htlc_id: Option, - /// The amount in msat. - pub amount_msat: u64, - /// The block height at which this HTLC expires. - pub cltv_expiry: u32, - /// The payment hash. - pub payment_hash: PaymentHash, - /// The state of the HTLC in the state machine. - /// - /// Determines on which commitment transactions the HTLC is included and what message the HTLC is - /// waiting for to advance to the next state. - /// - /// See [`OutboundHTLCStateDetails`] for information on the specific states. - /// - /// LDK will always fill this field in, but when downgrading to prior versions of LDK, new - /// states may result in `None` here. - pub state: Option, - /// The extra fee being skimmed off the top of this HTLC. - pub skimmed_fee_msat: Option, - /// Whether the HTLC has an output below the local dust limit. If so, the output will be trimmed - /// from the local commitment transaction and added to the commitment transaction fee. - /// For non-anchor channels, this takes into account the cost of the second-stage HTLC - /// transactions as well. - /// - /// When the local commitment transaction is broadcasted as part of a unilateral closure, - /// the value of this HTLC will therefore not be claimable but instead burned as a transaction - /// fee. - /// - /// Note that dust limits are specific to each party. An HTLC can be dust for the local - /// commitment transaction but not for the counterparty's commitment transaction and vice versa. - pub is_dust: bool, -} - -impl_writeable_tlv_based!(OutboundHTLCDetails, { - (0, htlc_id, required), - (2, amount_msat, required), - (4, cltv_expiry, required), - (6, payment_hash, required), - (7, state, upgradable_option), - (8, skimmed_fee_msat, required), - (10, is_dust, required), -}); - /// See AwaitingRemoteRevoke ChannelState for more info #[cfg_attr(test, derive(Clone, Debug, PartialEq))] enum HTLCUpdateAwaitingACK { @@@ -933,6 -1119,75 +933,75 @@@ pub(crate) struct ShutdownResult pub(crate) channel_funding_txo: Option, } + /// Tracks the transaction number, along with current and next commitment points. + /// This consolidates the logic to advance our commitment number and request new + /// commitment points from our signer. + #[derive(Debug, Copy, Clone)] + enum HolderCommitmentPoint { + // TODO: add a variant for before our first commitment point is retrieved + /// We've advanced our commitment number and are waiting on the next commitment point. + /// Until the `get_per_commitment_point` signer method becomes async, this variant + /// will not be used. + PendingNext { transaction_number: u64, current: PublicKey }, + /// Our current commitment point is ready, we've cached our next point, + /// and we are not pending a new one. + Available { transaction_number: u64, current: PublicKey, next: PublicKey }, + } + + impl HolderCommitmentPoint { + pub fn new(signer: &ChannelSignerType, secp_ctx: &Secp256k1) -> Self + where SP::Target: SignerProvider + { + HolderCommitmentPoint::Available { + transaction_number: INITIAL_COMMITMENT_NUMBER, + current: signer.as_ref().get_per_commitment_point(INITIAL_COMMITMENT_NUMBER, secp_ctx), + next: signer.as_ref().get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 1, secp_ctx), + } + } + + pub fn is_available(&self) -> bool { + if let HolderCommitmentPoint::Available { .. } = self { true } else { false } + } + + pub fn transaction_number(&self) -> u64 { + match self { + HolderCommitmentPoint::PendingNext { transaction_number, .. } => *transaction_number, + HolderCommitmentPoint::Available { transaction_number, .. } => *transaction_number, + } + } + + pub fn current_point(&self) -> PublicKey { + match self { + HolderCommitmentPoint::PendingNext { current, .. } => *current, + HolderCommitmentPoint::Available { current, .. } => *current, + } + } + + pub fn next_point(&self) -> Option { + match self { + HolderCommitmentPoint::PendingNext { .. } => None, + HolderCommitmentPoint::Available { next, .. } => Some(*next), + } + } + + pub fn advance(&mut self, signer: &ChannelSignerType, secp_ctx: &Secp256k1, logger: &L) + where SP::Target: SignerProvider, L::Target: Logger + { + if let HolderCommitmentPoint::Available { transaction_number, next, .. } = self { + *self = HolderCommitmentPoint::PendingNext { + transaction_number: *transaction_number - 1, + current: *next, + }; + } + + if let HolderCommitmentPoint::PendingNext { transaction_number, current } = self { + let next = signer.as_ref().get_per_commitment_point(*transaction_number - 1, secp_ctx); + log_trace!(logger, "Retrieved next per-commitment point {}", *transaction_number - 1); + *self = HolderCommitmentPoint::Available { transaction_number: *transaction_number, current: *current, next }; + } + } + } + /// If the majority of the channels funds are to the fundee and the initiator holds only just /// enough funds to cover their reserve value, channels are at risk of getting "stuck". Because the /// initiator controls the feerate, if they then go to increase the channel fee, they may have no @@@ -1111,7 -1366,7 +1180,7 @@@ pub(super) struct ChannelContext, @@@ -1553,6 -1808,9 +1622,9 @@@ impl ChannelContext wher let value_to_self_msat = our_funding_satoshis * 1000 + msg_push_msat; + let holder_signer = ChannelSignerType::Ecdsa(holder_signer); + let holder_commitment_point = HolderCommitmentPoint::new(&holder_signer, &secp_ctx); + // TODO(dual_funding): Checks for `funding_feerate_sat_per_1000_weight`? let channel_context = ChannelContext { @@@ -1578,11 -1836,11 +1650,11 @@@ latest_monitor_update_id: 0, - holder_signer: ChannelSignerType::Ecdsa(holder_signer), + holder_signer, shutdown_scriptpubkey, destination_script, - cur_holder_commitment_transaction_number: INITIAL_COMMITMENT_NUMBER, + holder_commitment_point, cur_counterparty_commitment_transaction_number: INITIAL_COMMITMENT_NUMBER, value_to_self_msat, @@@ -1777,6 -2035,9 +1849,9 @@@ let temporary_channel_id = temporary_channel_id.unwrap_or_else(|| ChannelId::temporary_from_entropy_source(entropy_source)); + let holder_signer = ChannelSignerType::Ecdsa(holder_signer); + let holder_commitment_point = HolderCommitmentPoint::new(&holder_signer, &secp_ctx); + Ok(Self { user_id, @@@ -1800,11 -2061,11 +1875,11 @@@ latest_monitor_update_id: 0, - holder_signer: ChannelSignerType::Ecdsa(holder_signer), + holder_signer, shutdown_scriptpubkey, destination_script, - cur_holder_commitment_transaction_number: INITIAL_COMMITMENT_NUMBER, + holder_commitment_point, cur_counterparty_commitment_transaction_number: INITIAL_COMMITMENT_NUMBER, value_to_self_msat, @@@ -2498,8 -2759,8 +2573,8 @@@ /// our counterparty!) /// The result is a transaction which we can revoke broadcastership of (ie a "local" transaction) /// TODO Some magic rust shit to compile-time check this? - fn build_holder_transaction_keys(&self, commitment_number: u64) -> TxCreationKeys { - let per_commitment_point = self.holder_signer.as_ref().get_per_commitment_point(commitment_number, &self.secp_ctx); + fn build_holder_transaction_keys(&self) -> TxCreationKeys { + let per_commitment_point = self.holder_commitment_point.current_point(); let delayed_payment_base = &self.get_holder_pubkeys().delayed_payment_basepoint; let htlc_basepoint = &self.get_holder_pubkeys().htlc_basepoint; let counterparty_pubkeys = self.get_counterparty_pubkeys(); @@@ -4195,9 -4456,9 +4270,9 @@@ impl Channel wher let funding_script = self.context.get_funding_redeemscript(); - let keys = self.context.build_holder_transaction_keys(self.context.cur_holder_commitment_transaction_number); + let keys = self.context.build_holder_transaction_keys(); - let commitment_stats = self.context.build_commitment_transaction(self.context.cur_holder_commitment_transaction_number, &keys, true, false, logger); + let commitment_stats = self.context.build_commitment_transaction(self.context.holder_commitment_point.transaction_number(), &keys, true, false, logger); let commitment_txid = { let trusted_tx = commitment_stats.tx.trust(); let bitcoin_tx = trusted_tx.built_transaction(); @@@ -4273,7 -4534,7 +4348,7 @@@ let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &self.context.channel_type, &keys); let htlc_sighashtype = if self.context.channel_type.supports_anchors_zero_fee_htlc_tx() { EcdsaSighashType::SinglePlusAnyoneCanPay } else { EcdsaSighashType::All }; - let htlc_sighash = hash_to_message!(&sighash::SighashCache::new(&htlc_tx).segwit_signature_hash(0, &htlc_redeemscript, htlc.amount_msat / 1000, htlc_sighashtype).unwrap()[..]); + let htlc_sighash = hash_to_message!(&sighash::SighashCache::new(&htlc_tx).p2wsh_signature_hash(0, &htlc_redeemscript, htlc.to_bitcoin_amount(), htlc_sighashtype).unwrap()[..]); log_trace!(logger, "Checking HTLC tx signature {} by key {} against tx {} (sighash {}) with redeemscript {} in channel {}.", log_bytes!(msg.htlc_signatures[idx].serialize_compact()[..]), log_bytes!(keys.countersignatory_htlc_key.to_public_key().serialize()), encode::serialize_hex(&htlc_tx), log_bytes!(htlc_sighash[..]), encode::serialize_hex(&htlc_redeemscript), &self.context.channel_id()); @@@ -4360,7 -4621,7 +4435,7 @@@ channel_id: Some(self.context.channel_id()), }; - self.context.cur_holder_commitment_transaction_number -= 1; + self.context.holder_commitment_point.advance(&self.context.holder_signer, &self.context.secp_ctx, logger); self.context.expecting_peer_commitment_signed = false; // Note that if we need_commitment & !AwaitingRemoteRevoke we'll call // build_commitment_no_status_check() next which will reset this to RAAFirst. @@@ -4871,8 -5132,8 +4946,8 @@@ // Before proposing a feerate update, check that we can actually afford the new fee. let dust_exposure_limiting_feerate = self.context.get_dust_exposure_limiting_feerate(&fee_estimator); let htlc_stats = self.context.get_pending_htlc_stats(Some(feerate_per_kw), dust_exposure_limiting_feerate); - let keys = self.context.build_holder_transaction_keys(self.context.cur_holder_commitment_transaction_number); - let commitment_stats = self.context.build_commitment_transaction(self.context.cur_holder_commitment_transaction_number, &keys, true, true, logger); + let keys = self.context.build_holder_transaction_keys(); + let commitment_stats = self.context.build_commitment_transaction(self.context.holder_commitment_point.transaction_number(), &keys, true, true, logger); let buffer_fee_msat = commit_tx_fee_sat(feerate_per_kw, commitment_stats.num_nondust_htlcs + htlc_stats.on_holder_tx_outbound_holding_cell_htlcs_count as usize + CONCURRENT_INBOUND_HTLC_FEE_BUFFER as usize, self.context.get_channel_type()) * 1000; let holder_balance_msat = commitment_stats.local_balance_msat - htlc_stats.outbound_holding_cell_msat; if holder_balance_msat < buffer_fee_msat + self.context.counterparty_selected_channel_reserve_satoshis.unwrap() * 1000 { @@@ -5054,12 -5315,7 +5129,7 @@@ assert!(!self.context.is_outbound() || self.context.minimum_depth == Some(0), "Funding transaction broadcast by the local client before it should have - LDK didn't do it!"); self.context.monitor_pending_channel_ready = false; - let next_per_commitment_point = self.context.holder_signer.as_ref().get_per_commitment_point(self.context.cur_holder_commitment_transaction_number, &self.context.secp_ctx); - Some(msgs::ChannelReady { - channel_id: self.context.channel_id(), - next_per_commitment_point, - short_channel_id_alias: Some(self.context.outbound_scid_alias), - }) + Some(self.get_channel_ready()) } else { None }; let announcement_sigs = self.get_announcement_sigs(node_signer, chain_hash, user_config, best_block_height, logger); @@@ -5145,7 -5401,7 +5215,7 @@@ self.context.get_funding_signed_msg(logger).1 } else { None }; let channel_ready = if funding_signed.is_some() { - self.check_get_channel_ready(0) + self.check_get_channel_ready(0, logger) } else { None }; log_trace!(logger, "Signer unblocked with {} commitment_update, {} funding_signed and {} channel_ready", @@@ -5161,8 -5417,11 +5231,11 @@@ } fn get_last_revoke_and_ack(&self) -> msgs::RevokeAndACK { - let next_per_commitment_point = self.context.holder_signer.as_ref().get_per_commitment_point(self.context.cur_holder_commitment_transaction_number, &self.context.secp_ctx); - let per_commitment_secret = self.context.holder_signer.as_ref().release_commitment_secret(self.context.cur_holder_commitment_transaction_number + 2); + debug_assert!(self.context.holder_commitment_point.transaction_number() <= INITIAL_COMMITMENT_NUMBER + 2); + // TODO: handle non-available case when get_per_commitment_point becomes async + debug_assert!(self.context.holder_commitment_point.is_available()); + let next_per_commitment_point = self.context.holder_commitment_point.current_point(); + let per_commitment_secret = self.context.holder_signer.as_ref().release_commitment_secret(self.context.holder_commitment_point.transaction_number() + 2); msgs::RevokeAndACK { channel_id: self.context.channel_id, per_commitment_secret, @@@ -5295,7 -5554,7 +5368,7 @@@ return Err(ChannelError::Close("Peer sent an invalid channel_reestablish to force close in a non-standard way".to_owned())); } - let our_commitment_transaction = INITIAL_COMMITMENT_NUMBER - self.context.cur_holder_commitment_transaction_number - 1; + let our_commitment_transaction = INITIAL_COMMITMENT_NUMBER - self.context.holder_commitment_point.transaction_number() - 1; if msg.next_remote_commitment_number > 0 { let expected_point = self.context.holder_signer.as_ref().get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - msg.next_remote_commitment_number + 1, &self.context.secp_ctx); let given_secret = SecretKey::from_slice(&msg.your_last_per_commitment_secret) @@@ -5357,13 -5616,8 +5430,8 @@@ } // We have OurChannelReady set! - let next_per_commitment_point = self.context.holder_signer.as_ref().get_per_commitment_point(self.context.cur_holder_commitment_transaction_number, &self.context.secp_ctx); return Ok(ReestablishResponses { - channel_ready: Some(msgs::ChannelReady { - channel_id: self.context.channel_id(), - next_per_commitment_point, - short_channel_id_alias: Some(self.context.outbound_scid_alias), - }), + channel_ready: Some(self.get_channel_ready()), raa: None, commitment_update: None, order: RAACommitmentOrder::CommitmentFirst, shutdown_msg, announcement_sigs, @@@ -5400,14 -5654,9 +5468,9 @@@ } let next_counterparty_commitment_number = INITIAL_COMMITMENT_NUMBER - self.context.cur_counterparty_commitment_transaction_number + if is_awaiting_remote_revoke { 1 } else { 0 }; - let channel_ready = if msg.next_local_commitment_number == 1 && INITIAL_COMMITMENT_NUMBER - self.context.cur_holder_commitment_transaction_number == 1 { + let channel_ready = if msg.next_local_commitment_number == 1 && INITIAL_COMMITMENT_NUMBER - self.context.holder_commitment_point.transaction_number() == 1 { // We should never have to worry about MonitorUpdateInProgress resending ChannelReady - let next_per_commitment_point = self.context.holder_signer.as_ref().get_per_commitment_point(self.context.cur_holder_commitment_transaction_number, &self.context.secp_ctx); - Some(msgs::ChannelReady { - channel_id: self.context.channel_id(), - next_per_commitment_point, - short_channel_id_alias: Some(self.context.outbound_scid_alias), - }) + Some(self.get_channel_ready()) } else { None }; if msg.next_local_commitment_number == next_counterparty_commitment_number { @@@ -5781,7 -6030,7 +5844,7 @@@ }; for outp in closing_tx.trust().built_transaction().output.iter() { - if !outp.script_pubkey.is_witness_program() && outp.value < MAX_STD_OUTPUT_DUST_LIMIT_SATOSHIS { + if !outp.script_pubkey.is_witness_program() && outp.value < Amount::from_sat(MAX_STD_OUTPUT_DUST_LIMIT_SATOSHIS) { return Err(ChannelError::Close("Remote sent us a closing_signed with a dust output. Always use segwit closing scripts!".to_owned())); } } @@@ -6053,7 -6302,7 +6116,7 @@@ } pub fn get_cur_holder_commitment_transaction_number(&self) -> u64 { - self.context.cur_holder_commitment_transaction_number + 1 + self.context.holder_commitment_point.transaction_number() + 1 } pub fn get_cur_counterparty_commitment_transaction_number(&self) -> u64 { @@@ -6168,7 -6417,7 +6231,7 @@@ debug_assert!(self.context.minimum_depth.unwrap_or(1) > 0); return true; } - if self.context.cur_holder_commitment_transaction_number == INITIAL_COMMITMENT_NUMBER - 1 && + if self.context.holder_commitment_point.transaction_number() == INITIAL_COMMITMENT_NUMBER - 1 && self.context.cur_counterparty_commitment_transaction_number == INITIAL_COMMITMENT_NUMBER - 1 { // If we're a 0-conf channel, we'll move beyond AwaitingChannelReady immediately even while // waiting for the initial monitor persistence. Thus, we check if our commitment @@@ -6227,7 -6476,9 +6290,9 @@@ self.context.channel_update_status = status; } - fn check_get_channel_ready(&mut self, height: u32) -> Option { + fn check_get_channel_ready(&mut self, height: u32, logger: &L) -> Option + where L::Target: Logger + { // Called: // * always when a new block/transactions are confirmed with the new height // * when funding is signed with a height of 0 @@@ -6247,6 -6498,8 +6312,8 @@@ // If we're still pending the signature on a funding transaction, then we're not ready to send a // channel_ready yet. if self.context.signer_pending_funding { + // TODO: set signer_pending_channel_ready + log_debug!(logger, "Can't produce channel_ready: the signer is pending funding."); return None; } @@@ -6279,22 -6532,35 +6346,35 @@@ false }; - if need_commitment_update { - if !self.context.channel_state.is_monitor_update_in_progress() { - if !self.context.channel_state.is_peer_disconnected() { - let next_per_commitment_point = - self.context.holder_signer.as_ref().get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 1, &self.context.secp_ctx); - return Some(msgs::ChannelReady { - channel_id: self.context.channel_id, - next_per_commitment_point, - short_channel_id_alias: Some(self.context.outbound_scid_alias), - }); - } - } else { - self.context.monitor_pending_channel_ready = true; - } + if !need_commitment_update { + log_debug!(logger, "Not producing channel_ready: we do not need a commitment update"); + return None; + } + + if self.context.channel_state.is_monitor_update_in_progress() { + log_debug!(logger, "Not producing channel_ready: a monitor update is in progress. Setting monitor_pending_channel_ready."); + self.context.monitor_pending_channel_ready = true; + return None; + } + + if self.context.channel_state.is_peer_disconnected() { + log_debug!(logger, "Not producing channel_ready: the peer is disconnected."); + return None; + } + + // TODO: when get_per_commiment_point becomes async, check if the point is + // available, if not, set signer_pending_channel_ready and return None + + Some(self.get_channel_ready()) + } + + fn get_channel_ready(&self) -> msgs::ChannelReady { + debug_assert!(self.context.holder_commitment_point.is_available()); + msgs::ChannelReady { + channel_id: self.context.channel_id(), + next_per_commitment_point: self.context.holder_commitment_point.current_point(), + short_channel_id_alias: Some(self.context.outbound_scid_alias), } - None } /// When a transaction is confirmed, we check whether it is or spends the funding transaction @@@ -6316,8 -6582,8 +6396,8 @@@ if self.context.funding_tx_confirmation_height == 0 { if tx.txid() == funding_txo.txid { let txo_idx = funding_txo.index as usize; - if txo_idx >= tx.output.len() || tx.output[txo_idx].script_pubkey != self.context.get_funding_redeemscript().to_v0_p2wsh() || - tx.output[txo_idx].value != self.context.channel_value_satoshis { + if txo_idx >= tx.output.len() || tx.output[txo_idx].script_pubkey != self.context.get_funding_redeemscript().to_p2wsh() || + tx.output[txo_idx].value.to_sat() != self.context.channel_value_satoshis { if self.context.is_outbound() { // If we generated the funding transaction and it doesn't match what it // should, the client is really broken and we should just panic and @@@ -6332,7 -6598,7 +6412,7 @@@ return Err(ClosureReason::ProcessingError { err: err_reason.to_owned() }); } else { if self.context.is_outbound() { - if !tx.is_coin_base() { + if !tx.is_coinbase() { for input in tx.input.iter() { if input.witness.is_empty() { // We generated a malleable funding transaction, implying we've @@@ -6352,7 -6618,7 +6432,7 @@@ } // If this is a coinbase transaction and not a 0-conf channel // we should update our min_depth to 100 to handle coinbase maturity - if tx.is_coin_base() && + if tx.is_coinbase() && self.context.minimum_depth.unwrap_or(0) > 0 && self.context.minimum_depth.unwrap_or(0) < COINBASE_MATURITY { self.context.minimum_depth = Some(COINBASE_MATURITY); @@@ -6361,7 -6627,7 +6441,7 @@@ // If we allow 1-conf funding, we may need to check for channel_ready here and // send it immediately instead of waiting for a best_block_updated call (which // may have already happened for this block). - if let Some(channel_ready) = self.check_get_channel_ready(height) { + if let Some(channel_ready) = self.check_get_channel_ready(height, logger) { log_info!(logger, "Sending a channel_ready to our peer for channel {}", &self.context.channel_id); let announcement_sigs = self.get_announcement_sigs(node_signer, chain_hash, user_config, height, logger); msgs = (Some(channel_ready), announcement_sigs); @@@ -6427,7 -6693,7 +6507,7 @@@ self.context.update_time_counter = cmp::max(self.context.update_time_counter, highest_header_time); - if let Some(channel_ready) = self.check_get_channel_ready(height) { + if let Some(channel_ready) = self.check_get_channel_ready(height, logger) { let announcement_sigs = if let Some((chain_hash, node_signer, user_config)) = chain_node_signer { self.get_announcement_sigs(node_signer, chain_hash, user_config, height, logger) } else { None }; @@@ -6730,7 -6996,7 +6810,7 @@@ // next_local_commitment_number is the next commitment_signed number we expect to // receive (indicating if they need to resend one that we missed). - next_local_commitment_number: INITIAL_COMMITMENT_NUMBER - self.context.cur_holder_commitment_transaction_number, + next_local_commitment_number: INITIAL_COMMITMENT_NUMBER - self.context.holder_commitment_point.transaction_number(), // We have to set next_remote_commitment_number to the next revoke_and_ack we expect to // receive, however we track it by the next commitment number for a remote transaction // (which is one further, as they always revoke previous commitment transaction, not @@@ -7282,7 -7548,7 +7362,7 @@@ impl OutboundV1Channel w } if self.context.commitment_secrets.get_min_seen_secret() != (1 << 48) || self.context.cur_counterparty_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER || - self.context.cur_holder_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER { + self.context.holder_commitment_point.transaction_number() != INITIAL_COMMITMENT_NUMBER { panic!("Should not have advanced channel commitment tx numbers prior to funding_created"); } @@@ -7296,7 -7562,7 +7376,7 @@@ // If the funding transaction is a coinbase transaction, we need to set the minimum depth to 100. // We can skip this if it is a zero-conf channel. - if funding_transaction.is_coin_base() && + if funding_transaction.is_coinbase() && self.context.minimum_depth.unwrap_or(0) > 0 && self.context.minimum_depth.unwrap_or(0) < COINBASE_MATURITY { self.context.minimum_depth = Some(COINBASE_MATURITY); @@@ -7337,7 -7603,7 +7417,7 @@@ /// Returns true if we can resume the channel by sending the [`msgs::OpenChannel`] again. pub fn is_resumable(&self) -> bool { !self.context.have_received_message() && - self.context.cur_holder_commitment_transaction_number == INITIAL_COMMITMENT_NUMBER + self.context.holder_commitment_point.transaction_number() == INITIAL_COMMITMENT_NUMBER } pub fn get_open_channel(&self, chain_hash: ChainHash) -> msgs::OpenChannel { @@@ -7348,11 -7614,12 +7428,12 @@@ panic!("Cannot generate an open_channel after we've moved forward"); } - if self.context.cur_holder_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER { + if self.context.holder_commitment_point.transaction_number() != INITIAL_COMMITMENT_NUMBER { panic!("Tried to send an open_channel for a channel that has already advanced"); } - let first_per_commitment_point = self.context.holder_signer.as_ref().get_per_commitment_point(self.context.cur_holder_commitment_transaction_number, &self.context.secp_ctx); + debug_assert!(self.context.holder_commitment_point.is_available()); + let first_per_commitment_point = self.context.holder_commitment_point.current_point(); let keys = self.context.get_holder_pubkeys(); msgs::OpenChannel { @@@ -7533,7 -7800,7 +7614,7 @@@ } if self.context.commitment_secrets.get_min_seen_secret() != (1 << 48) || self.context.cur_counterparty_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER || - self.context.cur_holder_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER { + self.context.holder_commitment_point.transaction_number() != INITIAL_COMMITMENT_NUMBER { panic!("Should not have advanced channel commitment tx numbers prior to funding_created"); } @@@ -7547,8 -7814,8 +7628,8 @@@ log_trace!(logger, "Initial counterparty tx for channel {} is: txid {} tx {}", &self.context.channel_id(), counterparty_initial_bitcoin_tx.txid, encode::serialize_hex(&counterparty_initial_bitcoin_tx.transaction)); - let holder_signer = self.context.build_holder_transaction_keys(self.context.cur_holder_commitment_transaction_number); - let initial_commitment_tx = self.context.build_commitment_transaction(self.context.cur_holder_commitment_transaction_number, &holder_signer, true, false, logger).tx; + let holder_signer = self.context.build_holder_transaction_keys(); + let initial_commitment_tx = self.context.build_commitment_transaction(self.context.holder_commitment_point.transaction_number(), &holder_signer, true, false, logger).tx; { let trusted_tx = initial_commitment_tx.trust(); let initial_commitment_bitcoin_tx = trusted_tx.built_transaction(); @@@ -7575,7 -7842,7 +7656,7 @@@ let funding_redeemscript = self.context.get_funding_redeemscript(); let funding_txo = self.context.get_funding_txo().unwrap(); - let funding_txo_script = funding_redeemscript.to_v0_p2wsh(); + let funding_txo_script = funding_redeemscript.to_p2wsh(); let obscure_factor = get_commitment_transaction_number_obscure_factor(&self.context.get_holder_pubkeys().payment_point, &self.context.get_counterparty_pubkeys().payment_point, self.context.is_outbound()); let shutdown_script = self.context.shutdown_scriptpubkey.clone().map(|script| script.into_inner()); let mut monitor_signer = signer_provider.derive_channel_signer(self.context.channel_value_satoshis, self.context.channel_keys_id); @@@ -7601,7 -7868,7 +7682,7 @@@ } else { self.context.channel_state = ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::new()); } - self.context.cur_holder_commitment_transaction_number -= 1; + self.context.holder_commitment_point.advance(&self.context.holder_signer, &self.context.secp_ctx, logger); self.context.cur_counterparty_commitment_transaction_number -= 1; log_info!(logger, "Received funding_signed from peer for channel {}", &self.context.channel_id()); @@@ -7612,7 -7879,7 +7693,7 @@@ dual_funding_channel_context: None, }; - let need_channel_ready = channel.check_get_channel_ready(0).is_some(); + let need_channel_ready = channel.check_get_channel_ready(0, logger).is_some(); channel.monitor_updating_paused(false, false, need_channel_ready, Vec::new(), Vec::new(), Vec::new()); Ok((channel, channel_monitor)) } @@@ -7737,7 -8004,7 +7818,7 @@@ impl InboundV1Channel wh ) { panic!("Tried to send accept_channel after channel had moved forward"); } - if self.context.cur_holder_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER { + if self.context.holder_commitment_point.transaction_number() != INITIAL_COMMITMENT_NUMBER { panic!("Tried to send an accept_channel for a channel that has already advanced"); } @@@ -7750,7 -8017,8 +7831,8 @@@ /// /// [`msgs::AcceptChannel`]: crate::ln::msgs::AcceptChannel fn generate_accept_channel_message(&self) -> msgs::AcceptChannel { - let first_per_commitment_point = self.context.holder_signer.as_ref().get_per_commitment_point(self.context.cur_holder_commitment_transaction_number, &self.context.secp_ctx); + debug_assert!(self.context.holder_commitment_point.is_available()); + let first_per_commitment_point = self.context.holder_commitment_point.current_point(); let keys = self.context.get_holder_pubkeys(); msgs::AcceptChannel { @@@ -7792,8 -8060,8 +7874,8 @@@ fn check_funding_created_signature(&mut self, sig: &Signature, logger: &L) -> Result where L::Target: Logger { let funding_script = self.context.get_funding_redeemscript(); - let keys = self.context.build_holder_transaction_keys(self.context.cur_holder_commitment_transaction_number); - let initial_commitment_tx = self.context.build_commitment_transaction(self.context.cur_holder_commitment_transaction_number, &keys, true, false, logger).tx; + let keys = self.context.build_holder_transaction_keys(); + let initial_commitment_tx = self.context.build_commitment_transaction(self.context.holder_commitment_point.transaction_number(), &keys, true, false, logger).tx; let trusted_tx = initial_commitment_tx.trust(); let initial_commitment_bitcoin_tx = trusted_tx.built_transaction(); let sighash = initial_commitment_bitcoin_tx.get_sighash_all(&funding_script, self.context.channel_value_satoshis); @@@ -7827,7 -8095,7 +7909,7 @@@ } if self.context.commitment_secrets.get_min_seen_secret() != (1 << 48) || self.context.cur_counterparty_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER || - self.context.cur_holder_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER { + self.context.holder_commitment_point.transaction_number() != INITIAL_COMMITMENT_NUMBER { panic!("Should not have advanced channel commitment tx numbers prior to funding_created"); } @@@ -7867,12 -8135,12 +7949,12 @@@ self.context.channel_state = ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::new()); self.context.channel_id = ChannelId::v1_from_funding_outpoint(funding_txo); self.context.cur_counterparty_commitment_transaction_number -= 1; - self.context.cur_holder_commitment_transaction_number -= 1; + self.context.holder_commitment_point.advance(&self.context.holder_signer, &self.context.secp_ctx, logger); let (counterparty_initial_commitment_tx, funding_signed) = self.context.get_funding_signed_msg(logger); let funding_redeemscript = self.context.get_funding_redeemscript(); - let funding_txo_script = funding_redeemscript.to_v0_p2wsh(); + let funding_txo_script = funding_redeemscript.to_p2wsh(); let obscure_factor = get_commitment_transaction_number_obscure_factor(&self.context.get_holder_pubkeys().payment_point, &self.context.get_counterparty_pubkeys().payment_point, self.context.is_outbound()); let shutdown_script = self.context.shutdown_scriptpubkey.clone().map(|script| script.into_inner()); let mut monitor_signer = signer_provider.derive_channel_signer(self.context.channel_value_satoshis, self.context.channel_keys_id); @@@ -7901,7 -8169,7 +7983,7 @@@ #[cfg(any(dual_funding, splicing))] dual_funding_channel_context: None, }; - let need_channel_ready = channel.check_get_channel_ready(0).is_some(); + let need_channel_ready = channel.check_get_channel_ready(0, logger).is_some(); channel.monitor_updating_paused(false, false, need_channel_ready, Vec::new(), Vec::new(), Vec::new()); Ok((channel, funding_signed, channel_monitor)) @@@ -7988,15 -8256,15 +8070,15 @@@ impl OutboundV2Channel w debug_assert!(false, "Cannot generate an open_channel2 after we've moved forward"); } - if self.context.cur_holder_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER { + if self.context.holder_commitment_point.transaction_number() != INITIAL_COMMITMENT_NUMBER { debug_assert!(false, "Tried to send an open_channel2 for a channel that has already advanced"); } let first_per_commitment_point = self.context.holder_signer.as_ref() - .get_per_commitment_point(self.context.cur_holder_commitment_transaction_number, + .get_per_commitment_point(self.context.holder_commitment_point.transaction_number(), &self.context.secp_ctx); let second_per_commitment_point = self.context.holder_signer.as_ref() - .get_per_commitment_point(self.context.cur_holder_commitment_transaction_number - 1, + .get_per_commitment_point(self.context.holder_commitment_point.transaction_number() - 1, &self.context.secp_ctx); let keys = self.context.get_holder_pubkeys(); @@@ -8130,7 -8398,7 +8212,7 @@@ impl InboundV2Channel wh ) { debug_assert!(false, "Tried to send accept_channel2 after channel had moved forward"); } - if self.context.cur_holder_commitment_transaction_number != INITIAL_COMMITMENT_NUMBER { + if self.context.holder_commitment_point.transaction_number() != INITIAL_COMMITMENT_NUMBER { debug_assert!(false, "Tried to send an accept_channel2 for a channel that has already advanced"); } @@@ -8144,9 -8412,9 +8226,9 @@@ /// [`msgs::AcceptChannelV2`]: crate::ln::msgs::AcceptChannelV2 fn generate_accept_channel_v2_message(&self) -> msgs::AcceptChannelV2 { let first_per_commitment_point = self.context.holder_signer.as_ref().get_per_commitment_point( - self.context.cur_holder_commitment_transaction_number, &self.context.secp_ctx); + self.context.holder_commitment_point.transaction_number(), &self.context.secp_ctx); let second_per_commitment_point = self.context.holder_signer.as_ref().get_per_commitment_point( - self.context.cur_holder_commitment_transaction_number - 1, &self.context.secp_ctx); + self.context.holder_commitment_point.transaction_number() - 1, &self.context.secp_ctx); let keys = self.context.get_holder_pubkeys(); msgs::AcceptChannelV2 { @@@ -8319,7 -8587,7 +8401,7 @@@ impl Writeable for Channel let mut malformed_htlcs: Option> = None; let mut monitor_pending_update_adds: Option> = None; + let mut cur_holder_commitment_point_opt: Option = None; + let mut next_holder_commitment_point_opt: Option = None; + read_tlv_fields!(reader, { (0, announcement_sigs, option), (1, minimum_depth, option), @@@ -8970,7 -9246,8 +9060,8 @@@ (39, pending_outbound_blinding_points_opt, optional_vec), (41, holding_cell_blinding_points_opt, optional_vec), (43, malformed_htlcs, optional_vec), // Added in 0.0.119 - // 45 and 47 are reserved for async signing + (45, cur_holder_commitment_point_opt, option), + (47, next_holder_commitment_point_opt, option), (49, local_initiated_shutdown, option), }); @@@ -9082,6 -9359,24 +9173,24 @@@ } } + // If we're restoring this channel for the first time after an upgrade, then we require that the + // signer be available so that we can immediately populate the current commitment point. Channel + // restoration will fail if this is not possible. + let holder_commitment_point = match (cur_holder_commitment_point_opt, next_holder_commitment_point_opt) { + (Some(current), Some(next)) => HolderCommitmentPoint::Available { + transaction_number: cur_holder_commitment_transaction_number, current, next + }, + (Some(current), _) => HolderCommitmentPoint::Available { + transaction_number: cur_holder_commitment_transaction_number, current, + next: holder_signer.get_per_commitment_point(cur_holder_commitment_transaction_number - 1, &secp_ctx), + }, + (_, _) => HolderCommitmentPoint::Available { + transaction_number: cur_holder_commitment_transaction_number, + current: holder_signer.get_per_commitment_point(cur_holder_commitment_transaction_number, &secp_ctx), + next: holder_signer.get_per_commitment_point(cur_holder_commitment_transaction_number - 1, &secp_ctx), + }, + }; + Ok(Channel { context: ChannelContext { user_id, @@@ -9107,7 -9402,7 +9216,7 @@@ shutdown_scriptpubkey, destination_script, - cur_holder_commitment_transaction_number, + holder_commitment_point, cur_counterparty_commitment_transaction_number, value_to_self_msat, @@@ -9216,12 -9511,11 +9325,12 @@@ #[cfg(test)] mod tests { use std::cmp; + use bitcoin::amount::Amount; use bitcoin::blockdata::constants::ChainHash; use bitcoin::blockdata::script::{ScriptBuf, Builder}; - use bitcoin::blockdata::transaction::{Transaction, TxOut}; + use bitcoin::blockdata::transaction::{Transaction, TxOut, Version}; use bitcoin::blockdata::opcodes; - use bitcoin::network::constants::Network; + use bitcoin::network::Network; use crate::ln::onion_utils::INVALID_ONION_BLINDING; use crate::ln::types::{PaymentHash, PaymentPreimage}; use crate::ln::channel_keys::{RevocationKey, RevocationBasepoint}; @@@ -9250,8 -9544,9 +9359,8 @@@ use bitcoin::hashes::sha256::Hash as Sha256; use bitcoin::hashes::Hash; use bitcoin::hashes::hex::FromHex; - use bitcoin::hash_types::WPubkeyHash; use bitcoin::blockdata::locktime::absolute::LockTime; - use bitcoin::address::{WitnessProgram, WitnessVersion}; + use bitcoin::{WitnessProgram, WitnessVersion, WPubkeyHash}; use crate::prelude::*; #[test] @@@ -9407,8 -9702,8 +9516,8 @@@ // Node A --> Node B: funding created let output_script = node_a_chan.context.get_funding_redeemscript(); - let tx = Transaction { version: 1, lock_time: LockTime::ZERO, input: Vec::new(), output: vec![TxOut { - value: 10000000, script_pubkey: output_script.clone(), + let tx = Transaction { version: Version::ONE, lock_time: LockTime::ZERO, input: Vec::new(), output: vec![TxOut { + value: Amount::from_sat(10000000), script_pubkey: output_script.clone(), }]}; let funding_outpoint = OutPoint{ txid: tx.txid(), index: 0 }; let funding_created_msg = node_a_chan.get_funding_created(tx.clone(), funding_outpoint, false, &&logger).map_err(|_| ()).unwrap(); @@@ -9536,8 -9831,8 +9645,8 @@@ // Node A --> Node B: funding created let output_script = node_a_chan.context.get_funding_redeemscript(); - let tx = Transaction { version: 1, lock_time: LockTime::ZERO, input: Vec::new(), output: vec![TxOut { - value: 10000000, script_pubkey: output_script.clone(), + let tx = Transaction { version: Version::ONE, lock_time: LockTime::ZERO, input: Vec::new(), output: vec![TxOut { + value: Amount::from_sat(10000000), script_pubkey: output_script.clone(), }]}; let funding_outpoint = OutPoint{ txid: tx.txid(), index: 0 }; let funding_created_msg = node_a_chan.get_funding_created(tx.clone(), funding_outpoint, false, &&logger).map_err(|_| ()).unwrap(); @@@ -9725,8 -10020,8 +9834,8 @@@ // Node A --> Node B: funding created let output_script = node_a_chan.context.get_funding_redeemscript(); - let tx = Transaction { version: 1, lock_time: LockTime::ZERO, input: Vec::new(), output: vec![TxOut { - value: 10000000, script_pubkey: output_script.clone(), + let tx = Transaction { version: Version::ONE, lock_time: LockTime::ZERO, input: Vec::new(), output: vec![TxOut { + value: Amount::from_sat(10000000), script_pubkey: output_script.clone(), }]}; let funding_outpoint = OutPoint{ txid: tx.txid(), index: 0 }; let funding_created_msg = node_a_chan.get_funding_created(tx.clone(), funding_outpoint, false, &&logger).map_err(|_| ()).unwrap(); @@@ -9792,8 -10087,8 +9901,8 @@@ &features, &outbound_chan.get_open_channel(ChainHash::using_genesis_block(network)), 7, &config, 0, &&logger, false ).unwrap(); outbound_chan.accept_channel(&inbound_chan.get_accept_channel_message(), &config.channel_handshake_limits, &features).unwrap(); - let tx = Transaction { version: 1, lock_time: LockTime::ZERO, input: Vec::new(), output: vec![TxOut { - value: 10000000, script_pubkey: outbound_chan.context.get_funding_redeemscript(), + let tx = Transaction { version: Version::ONE, lock_time: LockTime::ZERO, input: Vec::new(), output: vec![TxOut { + value: Amount::from_sat(10000000), script_pubkey: outbound_chan.context.get_funding_redeemscript(), }]}; let funding_outpoint = OutPoint{ txid: tx.txid(), index: 0 }; let funding_created = outbound_chan.get_funding_created(tx.clone(), funding_outpoint, false, &&logger).map_err(|_| ()).unwrap().unwrap(); @@@ -10050,7 -10345,7 +10159,7 @@@ &htlc, $opt_anchors, &keys.broadcaster_delayed_payment_key, &keys.revocation_key); let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, $opt_anchors, &keys); let htlc_sighashtype = if $opt_anchors.supports_anchors_zero_fee_htlc_tx() { EcdsaSighashType::SinglePlusAnyoneCanPay } else { EcdsaSighashType::All }; - let htlc_sighash = Message::from_slice(&sighash::SighashCache::new(&htlc_tx).segwit_signature_hash(0, &htlc_redeemscript, htlc.amount_msat / 1000, htlc_sighashtype).unwrap()[..]).unwrap(); + let htlc_sighash = Message::from_digest(sighash::SighashCache::new(&htlc_tx).p2wsh_signature_hash(0, &htlc_redeemscript, htlc.to_bitcoin_amount(), htlc_sighashtype).unwrap().as_raw_hash().to_byte_array()); assert!(secp_ctx.verify_ecdsa(&htlc_sighash, &remote_signature, &keys.countersignatory_htlc_key.to_public_key()).is_ok(), "verify counterparty htlc sig"); let mut preimage: Option = None; @@@ -10916,15 -11211,15 +11025,15 @@@ // Fund the channel with a batch funding transaction. let output_script = node_a_chan.context.get_funding_redeemscript(); let tx = Transaction { - version: 1, + version: Version::ONE, lock_time: LockTime::ZERO, input: Vec::new(), output: vec![ TxOut { - value: 10000000, script_pubkey: output_script.clone(), + value: Amount::from_sat(10000000), script_pubkey: output_script.clone(), }, TxOut { - value: 10000000, script_pubkey: Builder::new().into_script(), + value: Amount::from_sat(10000000), script_pubkey: Builder::new().into_script(), }, ]}; let funding_outpoint = OutPoint{ txid: tx.txid(), index: 0 }; @@@ -10981,6 -11276,6 +11090,6 @@@ // Clear the ChannelState::WaitingForBatch only when called by ChannelManager. node_a_chan.set_batch_ready(); assert_eq!(node_a_chan.context.channel_state, ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::THEIR_CHANNEL_READY)); - assert!(node_a_chan.check_get_channel_ready(0).is_some()); + assert!(node_a_chan.check_get_channel_ready(0, &&logger).is_some()); } }