use prelude::*;
use core::{cmp,mem,fmt};
use core::ops::Deref;
-#[cfg(any(test, feature = "fuzztarget", debug_assertions))]
+#[cfg(any(test, fuzzing, debug_assertions))]
use sync::Mutex;
use bitcoin::hashes::hex::ToHex;
// `next_remote_commit_tx_fee_msat` properly predict what the next commitment transaction fee will
// be, by comparing the cached values to the fee of the tranaction generated by
// `build_commitment_transaction`.
- #[cfg(any(test, feature = "fuzztarget"))]
+ #[cfg(any(test, fuzzing))]
next_local_commitment_tx_fee_info_cached: Mutex<Option<CommitmentTxInfoCached>>,
- #[cfg(any(test, feature = "fuzztarget"))]
+ #[cfg(any(test, fuzzing))]
next_remote_commitment_tx_fee_info_cached: Mutex<Option<CommitmentTxInfoCached>>,
/// lnd has a long-standing bug where, upon reconnection, if the channel is not yet confirmed
/// See-also <https://github.com/lightningnetwork/lnd/issues/4006>
pub workaround_lnd_bug_4006: Option<msgs::FundingLocked>,
- #[cfg(any(test, feature = "fuzztarget"))]
+ #[cfg(any(test, fuzzing))]
// When we receive an HTLC fulfill on an outbound path, we may immediately fulfill the
// corresponding HTLC on the inbound path. If, then, the outbound path channel is
// disconnected and reconnected (before we've exchange commitment_signed and revoke_and_ack
channel_type: ChannelTypeFeatures,
}
-#[cfg(any(test, feature = "fuzztarget"))]
+#[cfg(any(test, fuzzing))]
struct CommitmentTxInfoCached {
fee: u64,
total_pending_htlcs: usize,
announcement_sigs: None,
- #[cfg(any(test, feature = "fuzztarget"))]
+ #[cfg(any(test, fuzzing))]
next_local_commitment_tx_fee_info_cached: Mutex::new(None),
- #[cfg(any(test, feature = "fuzztarget"))]
+ #[cfg(any(test, fuzzing))]
next_remote_commitment_tx_fee_info_cached: Mutex::new(None),
workaround_lnd_bug_4006: None,
- #[cfg(any(test, feature = "fuzztarget"))]
+ #[cfg(any(test, fuzzing))]
historical_inbound_htlc_fulfills: HashSet::new(),
// We currently only actually support one channel type, so don't retry with new types
announcement_sigs: None,
- #[cfg(any(test, feature = "fuzztarget"))]
+ #[cfg(any(test, fuzzing))]
next_local_commitment_tx_fee_info_cached: Mutex::new(None),
- #[cfg(any(test, feature = "fuzztarget"))]
+ #[cfg(any(test, fuzzing))]
next_remote_commitment_tx_fee_info_cached: Mutex::new(None),
workaround_lnd_bug_4006: None,
- #[cfg(any(test, feature = "fuzztarget"))]
+ #[cfg(any(test, fuzzing))]
historical_inbound_htlc_fulfills: HashSet::new(),
channel_type,
}
}
if pending_idx == core::usize::MAX {
- #[cfg(any(test, feature = "fuzztarget"))]
+ #[cfg(any(test, fuzzing))]
// If we failed to find an HTLC to fulfill, make sure it was previously fulfilled and
// this is simply a duplicate claim, not previously failed and we lost funds.
debug_assert!(self.historical_inbound_htlc_fulfills.contains(&htlc_id_arg));
if htlc_id_arg == htlc_id {
// Make sure we don't leave latest_monitor_update_id incremented here:
self.latest_monitor_update_id -= 1;
- #[cfg(any(test, feature = "fuzztarget"))]
+ #[cfg(any(test, fuzzing))]
debug_assert!(self.historical_inbound_htlc_fulfills.contains(&htlc_id_arg));
return UpdateFulfillFetch::DuplicateClaim {};
}
self.holding_cell_htlc_updates.push(HTLCUpdateAwaitingACK::ClaimHTLC {
payment_preimage: payment_preimage_arg, htlc_id: htlc_id_arg,
});
- #[cfg(any(test, feature = "fuzztarget"))]
+ #[cfg(any(test, fuzzing))]
self.historical_inbound_htlc_fulfills.insert(htlc_id_arg);
return UpdateFulfillFetch::NewClaim { monitor_update, htlc_value_msat, msg: None };
}
- #[cfg(any(test, feature = "fuzztarget"))]
+ #[cfg(any(test, fuzzing))]
self.historical_inbound_htlc_fulfills.insert(htlc_id_arg);
{
}
}
if pending_idx == core::usize::MAX {
- #[cfg(any(test, feature = "fuzztarget"))]
+ #[cfg(any(test, fuzzing))]
// If we failed to find an HTLC to fail, make sure it was previously fulfilled and this
// is simply a duplicate fail, not previously failed and we failed-back too early.
debug_assert!(self.historical_inbound_htlc_fulfills.contains(&htlc_id_arg));
match pending_update {
&HTLCUpdateAwaitingACK::ClaimHTLC { htlc_id, .. } => {
if htlc_id_arg == htlc_id {
- #[cfg(any(test, feature = "fuzztarget"))]
+ #[cfg(any(test, fuzzing))]
debug_assert!(self.historical_inbound_htlc_fulfills.contains(&htlc_id_arg));
return Ok(None);
}
return Err(ChannelError::Close("Minimum confirmation depth must be at least 1".to_owned()));
}
+ if let Some(ty) = &msg.channel_type {
+ if *ty != self.channel_type {
+ return Err(ChannelError::Close("Channel Type in accept_channel didn't match the one sent in open_channel.".to_owned()));
+ }
+ } else if their_features.supports_channel_type() {
+ // Assume they've accepted the channel type as they said they understand it.
+ } else {
+ self.channel_type = ChannelTypeFeatures::from_counterparty_init(&their_features)
+ }
+
let counterparty_shutdown_scriptpubkey = if their_features.supports_upfront_shutdown_script() {
match &msg.shutdown_scriptpubkey {
&OptionalField::Present(ref script) => {
/// Returns transaction if there is pending funding transaction that is yet to broadcast
pub fn unbroadcasted_funding(&self) -> Option<Transaction> {
- if self.channel_state & (ChannelState::FundingCreated as u32) != 0 {
- self.funding_transaction.clone()
- } else {
- None
- }
+ if self.channel_state & (ChannelState::FundingCreated as u32) != 0 {
+ self.funding_transaction.clone()
+ } else {
+ None
+ }
}
/// Returns a HTLCStats about inbound pending htlcs
let num_htlcs = included_htlcs + addl_htlcs;
let res = Self::commit_tx_fee_msat(self.feerate_per_kw, num_htlcs, self.opt_anchors());
- #[cfg(any(test, feature = "fuzztarget"))]
+ #[cfg(any(test, fuzzing))]
{
let mut fee = res;
if fee_spike_buffer_htlc.is_some() {
let num_htlcs = included_htlcs + addl_htlcs;
let res = Self::commit_tx_fee_msat(self.feerate_per_kw, num_htlcs, self.opt_anchors());
- #[cfg(any(test, feature = "fuzztarget"))]
+ #[cfg(any(test, fuzzing))]
{
let mut fee = res;
if fee_spike_buffer_htlc.is_some() {
return Err((None, ChannelError::Close("Funding remote cannot afford proposed new fee".to_owned())));
}
}
- #[cfg(any(test, feature = "fuzztarget"))]
+ #[cfg(any(test, fuzzing))]
{
if self.is_outbound() {
let projected_commit_tx_info = self.next_local_commitment_tx_fee_info_cached.lock().unwrap().take();
return Err(ChannelError::Close("Received an unexpected revoke_and_ack".to_owned()));
}
- #[cfg(any(test, feature = "fuzztarget"))]
+ #[cfg(any(test, fuzzing))]
{
*self.next_local_commitment_tx_fee_info_cached.lock().unwrap() = None;
*self.next_remote_commitment_tx_fee_info_cached.lock().unwrap() = None;
Some(msgs::FundingLocked {
channel_id: self.channel_id(),
next_per_commitment_point,
+ short_channel_id_alias: None,
})
} else { None };
funding_locked: Some(msgs::FundingLocked {
channel_id: self.channel_id(),
next_per_commitment_point,
+ short_channel_id_alias: None,
}),
raa: None, commitment_update: None, mon_update: None,
order: RAACommitmentOrder::CommitmentFirst,
Some(msgs::FundingLocked {
channel_id: self.channel_id(),
next_per_commitment_point,
+ short_channel_id_alias: None,
})
} else { None };
return Some(msgs::FundingLocked {
channel_id: self.channel_id,
next_per_commitment_point,
+ short_channel_id_alias: None,
});
}
} else {
// 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
// tell them off. That said, because hash collisions happen with high
- // probability in fuzztarget mode, if we're fuzzing we just close the
+ // probability in fuzzing mode, if we're fuzzing we just close the
// channel and move on.
- #[cfg(not(feature = "fuzztarget"))]
+ #[cfg(not(fuzzing))]
panic!("Client called ChannelManager::funding_transaction_generated with bogus transaction!");
}
self.update_time_counter += 1;
if input.witness.is_empty() {
// We generated a malleable funding transaction, implying we've
// just exposed ourselves to funds loss to our counterparty.
- #[cfg(not(feature = "fuzztarget"))]
+ #[cfg(not(fuzzing))]
panic!("Client called ChannelManager::funding_transaction_generated with bogus transaction!");
}
}
Some(script) => script.clone().into_inner(),
None => Builder::new().into_script(),
}),
+ channel_type: Some(self.channel_type.clone()),
}
}
+ /// Enables the possibility for tests to extract a [`msgs::AcceptChannel`] message for an
+ /// inbound channel without accepting it.
+ ///
+ /// [`msgs::AcceptChannel`]: crate::ln::msgs::AcceptChannel
+ #[cfg(test)]
+ pub fn get_accept_channel_message(&self) -> msgs::AcceptChannel {
+ self.generate_accept_channel_message()
+ }
+
/// If an Err is returned, it is a ChannelError::Close (for get_outbound_funding_created)
fn get_outbound_funding_created_signature<L: Deref>(&mut self, logger: &L) -> Result<Signature, ChannelError> where L::Target: Logger {
let counterparty_keys = self.build_remote_transaction_keys()?;
// Prior to static_remotekey, my_current_per_commitment_point was critical to claiming
// current to_remote balances. However, it no longer has any use, and thus is now simply
// set to a dummy (but valid, as required by the spec) public key.
- // fuzztarget mode marks a subset of pubkeys as invalid so that we can hit "invalid pubkey"
+ // fuzzing mode marks a subset of pubkeys as invalid so that we can hit "invalid pubkey"
// branches, but we unwrap it below, so we arbitrarily select a dummy pubkey which is both
- // valid, and valid in fuzztarget mode's arbitrary validity criteria:
+ // valid, and valid in fuzzing mode's arbitrary validity criteria:
let mut pk = [2; 33]; pk[1] = 0xff;
let dummy_pubkey = PublicKey::from_slice(&pk).unwrap();
let data_loss_protect = if self.cur_counterparty_commitment_transaction_number + 1 < INITIAL_COMMITMENT_NUMBER {
let counterparty_commitment_txid = commitment_stats.tx.trust().txid();
let (signature, htlc_signatures);
- #[cfg(any(test, feature = "fuzztarget"))]
+ #[cfg(any(test, fuzzing))]
{
if !self.is_outbound() {
let projected_commit_tx_info = self.next_remote_commitment_tx_fee_info_cached.lock().unwrap().take();
self.channel_update_status.write(writer)?;
- #[cfg(any(test, feature = "fuzztarget"))]
+ #[cfg(any(test, fuzzing))]
(self.historical_inbound_htlc_fulfills.len() as u64).write(writer)?;
- #[cfg(any(test, feature = "fuzztarget"))]
+ #[cfg(any(test, fuzzing))]
for htlc in self.historical_inbound_htlc_fulfills.iter() {
htlc.write(writer)?;
}
let channel_update_status = Readable::read(reader)?;
- #[cfg(any(test, feature = "fuzztarget"))]
+ #[cfg(any(test, fuzzing))]
let mut historical_inbound_htlc_fulfills = HashSet::new();
- #[cfg(any(test, feature = "fuzztarget"))]
+ #[cfg(any(test, fuzzing))]
{
let htlc_fulfills_len: u64 = Readable::read(reader)?;
for _ in 0..htlc_fulfills_len {
announcement_sigs,
- #[cfg(any(test, feature = "fuzztarget"))]
+ #[cfg(any(test, fuzzing))]
next_local_commitment_tx_fee_info_cached: Mutex::new(None),
- #[cfg(any(test, feature = "fuzztarget"))]
+ #[cfg(any(test, fuzzing))]
next_remote_commitment_tx_fee_info_cached: Mutex::new(None),
workaround_lnd_bug_4006: None,
- #[cfg(any(test, feature = "fuzztarget"))]
+ #[cfg(any(test, fuzzing))]
historical_inbound_htlc_fulfills,
channel_type: channel_type.unwrap(),
use ln::chan_utils::{ChannelPublicKeys, HolderCommitmentTransaction, CounterpartyChannelTransactionParameters, htlc_success_tx_weight, htlc_timeout_tx_weight};
use chain::BestBlock;
use chain::chaininterface::{FeeEstimator,ConfirmationTarget};
- use chain::keysinterface::{InMemorySigner, KeyMaterial, KeysInterface, BaseSign};
+ use chain::keysinterface::{InMemorySigner, Recipient, KeyMaterial, KeysInterface, BaseSign};
use chain::transaction::OutPoint;
use util::config::UserConfig;
use util::enforcing_trait_impls::EnforcingSigner;
impl KeysInterface for Keys {
type Signer = InMemorySigner;
- fn get_node_secret(&self) -> SecretKey { panic!(); }
+ fn get_node_secret(&self, _recipient: Recipient) -> Result<SecretKey, ()> { panic!(); }
fn get_inbound_payment_key_material(&self) -> KeyMaterial { panic!(); }
fn get_destination_script(&self) -> Script {
let secp_ctx = Secp256k1::signing_only();
}
fn get_secure_random_bytes(&self) -> [u8; 32] { [0; 32] }
fn read_chan_signer(&self, _data: &[u8]) -> Result<Self::Signer, DecodeError> { panic!(); }
- fn sign_invoice(&self, _hrp_bytes: &[u8], _invoice_data: &[u5]) -> Result<RecoverableSignature, ()> { panic!(); }
+ fn sign_invoice(&self, _hrp_bytes: &[u8], _invoice_data: &[u5], _recipient: Recipient) -> Result<RecoverableSignature, ()> { panic!(); }
}
fn public_from_secret_hex(secp_ctx: &Secp256k1<All>, hex: &str) -> PublicKey {