use prelude::*;
use core::{cmp, mem};
use core::cell::RefCell;
-use std::collections::{HashMap, hash_map, HashSet};
use std::io::{Cursor, Read};
use std::sync::{Arc, Condvar, Mutex, MutexGuard, RwLock, RwLockReadGuard};
use core::sync::atomic::{AtomicUsize, Ordering};
/// Typically, the block-specific parameters are derived from the best block hash for the network,
/// as a newly constructed `ChannelManager` will not have created any channels yet. These parameters
/// are not needed when deserializing a previously constructed `ChannelManager`.
+#[derive(Clone, Copy, PartialEq)]
pub struct ChainParameters {
/// The network for determining the `chain_hash` in Lightning messages.
pub network: Network,
}
/// The best known block as identified by its hash and height.
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, PartialEq)]
pub struct BestBlock {
block_hash: BlockHash,
height: u32,
}
#[cfg(any(test, feature = "_test_utils"))]
- pub(crate) fn test_process_background_events(&self) {
+ /// Process background events, for functional testing
+ pub fn test_process_background_events(&self) {
self.process_background_events();
}
}
fn internal_channel_reestablish(&self, counterparty_node_id: &PublicKey, msg: &msgs::ChannelReestablish) -> Result<(), MsgHandleErrInternal> {
- let (htlcs_failed_forward, chan_restoration_res) = {
+ let (htlcs_failed_forward, need_lnd_workaround, chan_restoration_res) = {
let mut channel_state_lock = self.channel_state.lock().unwrap();
let channel_state = &mut *channel_state_lock;
msg,
});
}
- (htlcs_failed_forward, handle_chan_restoration_locked!(self, channel_state_lock, channel_state, chan, revoke_and_ack, commitment_update, order, monitor_update_opt, Vec::new(), None, funding_locked))
+ let need_lnd_workaround = chan.get_mut().workaround_lnd_bug_4006.take();
+ (htlcs_failed_forward, need_lnd_workaround,
+ handle_chan_restoration_locked!(self, channel_state_lock, channel_state, chan, revoke_and_ack, commitment_update, order, monitor_update_opt, Vec::new(), None, funding_locked))
},
hash_map::Entry::Vacant(_) => return Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel".to_owned(), msg.channel_id))
}
};
post_handle_chan_restoration!(self, chan_restoration_res);
self.fail_holding_cell_htlcs(htlcs_failed_forward, msg.channel_id);
+
+ if let Some(funding_locked_msg) = need_lnd_workaround {
+ self.internal_funding_locked(counterparty_node_id, &funding_locked_msg)?;
+ }
Ok(())
}
const SERIALIZATION_VERSION: u8 = 1;
const MIN_SERIALIZATION_VERSION: u8 = 1;
-impl Writeable for PendingHTLCInfo {
- fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
- match &self.routing {
- &PendingHTLCRouting::Forward { ref onion_packet, ref short_channel_id } => {
- 0u8.write(writer)?;
- onion_packet.write(writer)?;
- short_channel_id.write(writer)?;
- },
- &PendingHTLCRouting::Receive { ref payment_data, ref incoming_cltv_expiry } => {
- 1u8.write(writer)?;
- payment_data.payment_secret.write(writer)?;
- payment_data.total_msat.write(writer)?;
- incoming_cltv_expiry.write(writer)?;
- },
- }
- self.incoming_shared_secret.write(writer)?;
- self.payment_hash.write(writer)?;
- self.amt_to_forward.write(writer)?;
- self.outgoing_cltv_value.write(writer)?;
- Ok(())
- }
-}
-
-impl Readable for PendingHTLCInfo {
- fn read<R: ::std::io::Read>(reader: &mut R) -> Result<PendingHTLCInfo, DecodeError> {
- Ok(PendingHTLCInfo {
- routing: match Readable::read(reader)? {
- 0u8 => PendingHTLCRouting::Forward {
- onion_packet: Readable::read(reader)?,
- short_channel_id: Readable::read(reader)?,
- },
- 1u8 => PendingHTLCRouting::Receive {
- payment_data: msgs::FinalOnionHopData {
- payment_secret: Readable::read(reader)?,
- total_msat: Readable::read(reader)?,
- },
- incoming_cltv_expiry: Readable::read(reader)?,
- },
- _ => return Err(DecodeError::InvalidValue),
- },
- incoming_shared_secret: Readable::read(reader)?,
- payment_hash: Readable::read(reader)?,
- amt_to_forward: Readable::read(reader)?,
- outgoing_cltv_value: Readable::read(reader)?,
- })
- }
-}
-
-impl Writeable for HTLCFailureMsg {
- fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
- match self {
- &HTLCFailureMsg::Relay(ref fail_msg) => {
- 0u8.write(writer)?;
- fail_msg.write(writer)?;
- },
- &HTLCFailureMsg::Malformed(ref fail_msg) => {
- 1u8.write(writer)?;
- fail_msg.write(writer)?;
- }
- }
- Ok(())
- }
-}
-
-impl Readable for HTLCFailureMsg {
- fn read<R: ::std::io::Read>(reader: &mut R) -> Result<HTLCFailureMsg, DecodeError> {
- match <u8 as Readable>::read(reader)? {
- 0 => Ok(HTLCFailureMsg::Relay(Readable::read(reader)?)),
- 1 => Ok(HTLCFailureMsg::Malformed(Readable::read(reader)?)),
- _ => Err(DecodeError::InvalidValue),
- }
- }
-}
-
-impl Writeable for PendingHTLCStatus {
- fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
- match self {
- &PendingHTLCStatus::Forward(ref forward_info) => {
- 0u8.write(writer)?;
- forward_info.write(writer)?;
- },
- &PendingHTLCStatus::Fail(ref fail_msg) => {
- 1u8.write(writer)?;
- fail_msg.write(writer)?;
- }
- }
- Ok(())
- }
-}
-
-impl Readable for PendingHTLCStatus {
- fn read<R: ::std::io::Read>(reader: &mut R) -> Result<PendingHTLCStatus, DecodeError> {
- match <u8 as Readable>::read(reader)? {
- 0 => Ok(PendingHTLCStatus::Forward(Readable::read(reader)?)),
- 1 => Ok(PendingHTLCStatus::Fail(Readable::read(reader)?)),
- _ => Err(DecodeError::InvalidValue),
- }
- }
-}
-
-impl_writeable!(HTLCPreviousHopData, 0, {
- short_channel_id,
- outpoint,
- htlc_id,
- incoming_packet_shared_secret
-});
-
-impl Writeable for ClaimableHTLC {
- fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
- self.prev_hop.write(writer)?;
- self.value.write(writer)?;
- self.payment_data.payment_secret.write(writer)?;
- self.payment_data.total_msat.write(writer)?;
- self.cltv_expiry.write(writer)
- }
-}
-
-impl Readable for ClaimableHTLC {
- fn read<R: ::std::io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
- Ok(ClaimableHTLC {
- prev_hop: Readable::read(reader)?,
- value: Readable::read(reader)?,
- payment_data: msgs::FinalOnionHopData {
- payment_secret: Readable::read(reader)?,
- total_msat: Readable::read(reader)?,
- },
- cltv_expiry: Readable::read(reader)?,
- })
- }
-}
-
-impl Writeable for HTLCSource {
- fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
- match self {
- &HTLCSource::PreviousHopData(ref hop_data) => {
- 0u8.write(writer)?;
- hop_data.write(writer)?;
- },
- &HTLCSource::OutboundRoute { ref path, ref session_priv, ref first_hop_htlc_msat } => {
- 1u8.write(writer)?;
- path.write(writer)?;
- session_priv.write(writer)?;
- first_hop_htlc_msat.write(writer)?;
- }
- }
- Ok(())
- }
-}
-
-impl Readable for HTLCSource {
- fn read<R: ::std::io::Read>(reader: &mut R) -> Result<HTLCSource, DecodeError> {
- match <u8 as Readable>::read(reader)? {
- 0 => Ok(HTLCSource::PreviousHopData(Readable::read(reader)?)),
- 1 => Ok(HTLCSource::OutboundRoute {
- path: Readable::read(reader)?,
- session_priv: Readable::read(reader)?,
- first_hop_htlc_msat: Readable::read(reader)?,
- }),
- _ => Err(DecodeError::InvalidValue),
- }
- }
-}
-
-impl Writeable for HTLCFailReason {
- fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
- match self {
- &HTLCFailReason::LightningError { ref err } => {
- 0u8.write(writer)?;
- err.write(writer)?;
- },
- &HTLCFailReason::Reason { ref failure_code, ref data } => {
- 1u8.write(writer)?;
- failure_code.write(writer)?;
- data.write(writer)?;
- }
- }
- Ok(())
- }
-}
-
-impl Readable for HTLCFailReason {
- fn read<R: ::std::io::Read>(reader: &mut R) -> Result<HTLCFailReason, DecodeError> {
- match <u8 as Readable>::read(reader)? {
- 0 => Ok(HTLCFailReason::LightningError { err: Readable::read(reader)? }),
- 1 => Ok(HTLCFailReason::Reason {
- failure_code: Readable::read(reader)?,
- data: Readable::read(reader)?,
- }),
- _ => Err(DecodeError::InvalidValue),
- }
- }
-}
-
-impl Writeable for HTLCForwardInfo {
- fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
- match self {
- &HTLCForwardInfo::AddHTLC { ref prev_short_channel_id, ref prev_funding_outpoint, ref prev_htlc_id, ref forward_info } => {
- 0u8.write(writer)?;
- prev_short_channel_id.write(writer)?;
- prev_funding_outpoint.write(writer)?;
- prev_htlc_id.write(writer)?;
- forward_info.write(writer)?;
- },
- &HTLCForwardInfo::FailHTLC { ref htlc_id, ref err_packet } => {
- 1u8.write(writer)?;
- htlc_id.write(writer)?;
- err_packet.write(writer)?;
- },
- }
- Ok(())
- }
-}
-
-impl Readable for HTLCForwardInfo {
- fn read<R: ::std::io::Read>(reader: &mut R) -> Result<HTLCForwardInfo, DecodeError> {
- match <u8 as Readable>::read(reader)? {
- 0 => Ok(HTLCForwardInfo::AddHTLC {
- prev_short_channel_id: Readable::read(reader)?,
- prev_funding_outpoint: Readable::read(reader)?,
- prev_htlc_id: Readable::read(reader)?,
- forward_info: Readable::read(reader)?,
- }),
- 1 => Ok(HTLCForwardInfo::FailHTLC {
- htlc_id: Readable::read(reader)?,
- err_packet: Readable::read(reader)?,
- }),
- _ => Err(DecodeError::InvalidValue),
- }
- }
-}
-
-impl_writeable!(PendingInboundPayment, 0, {
- payment_secret,
- expiry_time,
- user_payment_id,
- payment_preimage,
- min_value_msat
-});
+impl_writeable_tlv_based_enum!(PendingHTLCRouting,
+ (0, Forward) => {
+ (0, onion_packet),
+ (2, short_channel_id),
+ }, {}, {},
+ (1, Receive) => {
+ (0, payment_data),
+ (2, incoming_cltv_expiry),
+ }, {}, {}
+;);
+
+impl_writeable_tlv_based!(PendingHTLCInfo, {
+ (0, routing),
+ (2, incoming_shared_secret),
+ (4, payment_hash),
+ (6, amt_to_forward),
+ (8, outgoing_cltv_value)
+}, {}, {});
+
+impl_writeable_tlv_based_enum!(HTLCFailureMsg, ;
+ (0, Relay),
+ (1, Malformed),
+);
+impl_writeable_tlv_based_enum!(PendingHTLCStatus, ;
+ (0, Forward),
+ (1, Fail),
+);
+
+impl_writeable_tlv_based!(HTLCPreviousHopData, {
+ (0, short_channel_id),
+ (2, outpoint),
+ (4, htlc_id),
+ (6, incoming_packet_shared_secret)
+}, {}, {});
+
+impl_writeable_tlv_based!(ClaimableHTLC, {
+ (0, prev_hop),
+ (2, value),
+ (4, payment_data),
+ (6, cltv_expiry),
+}, {}, {});
+
+impl_writeable_tlv_based_enum!(HTLCSource,
+ (0, OutboundRoute) => {
+ (0, session_priv),
+ (2, first_hop_htlc_msat),
+ }, {}, {
+ (4, path),
+ };
+ (1, PreviousHopData)
+);
+
+impl_writeable_tlv_based_enum!(HTLCFailReason,
+ (0, LightningError) => {
+ (0, err),
+ }, {}, {},
+ (1, Reason) => {
+ (0, failure_code),
+ }, {}, {
+ (2, data),
+ },
+;);
+
+impl_writeable_tlv_based_enum!(HTLCForwardInfo,
+ (0, AddHTLC) => {
+ (0, forward_info),
+ (2, prev_short_channel_id),
+ (4, prev_htlc_id),
+ (6, prev_funding_outpoint),
+ }, {}, {},
+ (1, FailHTLC) => {
+ (0, htlc_id),
+ (2, err_packet),
+ }, {}, {},
+;);
+
+impl_writeable_tlv_based!(PendingInboundPayment, {
+ (0, payment_secret),
+ (2, expiry_time),
+ (4, user_payment_id),
+ (6, payment_preimage),
+ (8, min_value_msat),
+}, {}, {});
impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> Writeable for ChannelManager<Signer, M, T, K, F, L>
where M::Target: chain::Watch<Signer>,
use bitcoin::hashes::sha256::Hash as Sha256;
use bitcoin::{Block, BlockHeader, Transaction, TxOut};
- use std::sync::Mutex;
+ use std::sync::{Arc, Mutex};
use test::Bencher;
let network = bitcoin::Network::Testnet;
let genesis_hash = bitcoin::blockdata::constants::genesis_block(network).header.block_hash();
- let tx_broadcaster = test_utils::TestBroadcaster{txn_broadcasted: Mutex::new(Vec::new())};
+ let tx_broadcaster = test_utils::TestBroadcaster{txn_broadcasted: Mutex::new(Vec::new()), blocks: Arc::new(Mutex::new(Vec::new()))};
let fee_estimator = test_utils::TestFeeEstimator { sat_per_kw: 253 };
let mut config: UserConfig = Default::default();