// 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;
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;
use crate::chain::chaininterface::{FeeEstimator, ConfirmationTarget, LowerBoundedFeeEstimator};
use crate::chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateStep, LATENCY_GRACE_PERIOD_BLOCKS, CLOSED_CHANNEL_UPDATE_ID};
use crate::chain::transaction::{OutPoint, TransactionData};
-use crate::sign::ecdsa::{EcdsaChannelSigner, WriteableEcdsaChannelSigner};
+use crate::sign::ecdsa::EcdsaChannelSigner;
use crate::sign::{EntropySource, ChannelSigner, SignerProvider, NodeSigner, Recipient};
use crate::events::ClosureReason;
use crate::routing::gossip::NodeId;
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<InboundHTLCStateDetails> {
fn from(state: &InboundHTLCState) -> Option<InboundHTLCStateDetails> {
match state {
}
}
-impl_writeable_tlv_based_enum_upgradable!(InboundHTLCStateDetails,
- (0, AwaitingRemoteRevokeToAdd) => {},
- (2, Committed) => {},
- (4, AwaitingRemoteRevokeToRemoveFulfill) => {},
- (6, AwaitingRemoteRevokeToRemoveFail) => {};
-);
-
struct InboundHTLCOutput {
htlc_id: u64,
amount_msat: u64,
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<InboundHTLCStateDetails>,
- /// 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
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 {
}
}
-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 {
skimmed_fee_msat: Option<u64>,
}
-/// 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<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 [`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<OutboundHTLCStateDetails>,
- /// The extra fee being skimmed off the top of this HTLC.
- pub skimmed_fee_msat: Option<u64>,
- /// 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 {
pub logger: &'a L,
pub peer_id: Option<PublicKey>,
pub channel_id: Option<ChannelId>,
+ pub payment_hash: Option<PaymentHash>,
}
impl<'a, L: Deref> Logger for WithChannelContext<'a, L> where L::Target: Logger {
fn log(&self, mut record: Record) {
record.peer_id = self.peer_id;
record.channel_id = self.channel_id;
+ record.payment_hash = self.payment_hash;
self.logger.log(record)
}
}
impl<'a, 'b, L: Deref> WithChannelContext<'a, L>
where L::Target: Logger {
- pub(super) fn from<S: Deref>(logger: &'a L, context: &'b ChannelContext<S>) -> Self
+ pub(super) fn from<S: Deref>(logger: &'a L, context: &'b ChannelContext<S>, payment_hash: Option<PaymentHash>) -> Self
where S::Target: SignerProvider
{
WithChannelContext {
logger,
peer_id: Some(context.counterparty_node_id),
channel_id: Some(context.channel_id),
+ payment_hash
}
}
}
/// Either the height at which this channel was created or the height at which it was last
/// serialized if it was serialized by versions prior to 0.0.103.
/// We use this to close if funding is never broadcasted.
- channel_creation_height: u32,
+ pub(super) channel_creation_height: u32,
counterparty_dust_limit_satoshis: u64,
L::Target: Logger,
SP::Target: SignerProvider,
{
- let logger = WithContext::from(logger, Some(counterparty_node_id), Some(open_channel_fields.temporary_channel_id));
+ let logger = WithContext::from(logger, Some(counterparty_node_id), Some(open_channel_fields.temporary_channel_id), None);
let announced_channel = if (open_channel_fields.channel_flags & 1) == 1 { true } else { false };
let channel_value_satoshis = our_funding_satoshis.saturating_add(open_channel_fields.funding_satoshis);
impl<SP: Deref> Channel<SP> where
SP::Target: SignerProvider,
- <SP::Target as SignerProvider>::EcdsaSigner: WriteableEcdsaChannelSigner
+ <SP::Target as SignerProvider>::EcdsaSigner: EcdsaChannelSigner
{
fn check_remote_fee<F: Deref, L: Deref>(
channel_type: &ChannelTypeFeatures, fee_estimator: &LowerBoundedFeeEstimator<F>,
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());
};
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()));
}
}
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
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
}
// 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);
// 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);
Ok(self.get_open_channel(chain_hash))
}
+ /// 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
+ }
+
pub fn get_open_channel(&self, chain_hash: ChainHash) -> msgs::OpenChannel {
if !self.context.is_outbound() {
panic!("Tried to open a channel for an inbound channel?");
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);
F::Target: FeeEstimator,
L::Target: Logger,
{
- let logger = WithContext::from(logger, Some(counterparty_node_id), Some(msg.common_fields.temporary_channel_id));
+ let logger = WithContext::from(logger, Some(counterparty_node_id), Some(msg.common_fields.temporary_channel_id), None);
// First check the channel type is known, failing before we do anything else if we don't
// support this channel type.
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);
#[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};
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]
// 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();
// 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();
// 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();
&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();
&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<PaymentPreimage> = None;
// 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 };