use crate::chain::keysinterface::SpendableOutputDescriptor;
#[cfg(anchors)]
use crate::ln::chan_utils::{self, ChannelTransactionParameters, HTLCOutputInCommitment};
use crate::ln::channelmanager::{InterceptId, PaymentId};
use crate::ln::channel::FUNDING_CONF_DEADLINE_BLOCKS;
use crate::ln::features::ChannelTypeFeatures;
use crate::ln::msgs;
use crate::ln::msgs::DecodeError;
use crate::ln::{PaymentPreimage, PaymentHash, PaymentSecret};
use crate::routing::gossip::NetworkUpdate;
use crate::util::ser::{BigSize, FixedLengthReader, Writeable, Writer, MaybeReadable, Readable, WithoutLength, OptionDeserWrapper};
use crate::routing::router::{RouteHop, RouteParameters};
use bitcoin::{PackedLockTime, Transaction};
#[cfg(anchors)]
use bitcoin::{OutPoint, Txid, TxIn, TxOut, Witness};
use bitcoin::blockdata::script::Script;
use bitcoin::hashes::Hash;
use bitcoin::hashes::sha256::Hash as Sha256;
use bitcoin::secp256k1::PublicKey;
#[cfg(anchors)]
use bitcoin::secp256k1::{self, Secp256k1};
#[cfg(anchors)]
use bitcoin::secp256k1::ecdsa::Signature;
use crate::io;
use crate::prelude::*;
use core::time::Duration;
use core::ops::Deref;
use crate::sync::Arc;
#[derive(Clone, Debug)]
pub enum PaymentPurpose {
InvoicePayment {
payment_preimage: Option<PaymentPreimage>,
payment_secret: PaymentSecret,
},
SpontaneousPayment(PaymentPreimage),
}
impl_writeable_tlv_based_enum!(PaymentPurpose,
(0, InvoicePayment) => {
(0, payment_preimage, option),
(2, payment_secret, required),
};
(2, SpontaneousPayment)
);
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum ClosureReason {
CounterpartyForceClosed {
peer_msg: String,
},
HolderForceClosed,
CooperativeClosure,
CommitmentTxConfirmed,
FundingTimedOut,
ProcessingError {
err: String,
},
DisconnectedPeer,
OutdatedChannelManager
}
impl core::fmt::Display for ClosureReason {
fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
f.write_str("Channel closed because ")?;
match self {
ClosureReason::CounterpartyForceClosed { peer_msg } => {
f.write_str("counterparty force-closed with message ")?;
f.write_str(&peer_msg)
},
ClosureReason::HolderForceClosed => f.write_str("user manually force-closed the channel"),
ClosureReason::CooperativeClosure => f.write_str("the channel was cooperatively closed"),
ClosureReason::CommitmentTxConfirmed => f.write_str("commitment or closing transaction was confirmed on chain."),
ClosureReason::FundingTimedOut => write!(f, "funding transaction failed to confirm within {} blocks", FUNDING_CONF_DEADLINE_BLOCKS),
ClosureReason::ProcessingError { err } => {
f.write_str("of an exception: ")?;
f.write_str(&err)
},
ClosureReason::DisconnectedPeer => f.write_str("the peer disconnected prior to the channel being funded"),
ClosureReason::OutdatedChannelManager => f.write_str("the ChannelManager read from disk was stale compared to ChannelMonitor(s)"),
}
}
}
impl_writeable_tlv_based_enum_upgradable!(ClosureReason,
(0, CounterpartyForceClosed) => { (1, peer_msg, required) },
(1, FundingTimedOut) => {},
(2, HolderForceClosed) => {},
(6, CommitmentTxConfirmed) => {},
(4, CooperativeClosure) => {},
(8, ProcessingError) => { (1, err, required) },
(10, DisconnectedPeer) => {},
(12, OutdatedChannelManager) => {},
);
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum HTLCDestination {
NextHopChannel {
node_id: Option<PublicKey>,
channel_id: [u8; 32],
},
UnknownNextHop {
requested_forward_scid: u64,
},
InvalidForward {
requested_forward_scid: u64
},
FailedPayment {
payment_hash: PaymentHash
},
}
impl_writeable_tlv_based_enum_upgradable!(HTLCDestination,
(0, NextHopChannel) => {
(0, node_id, required),
(2, channel_id, required),
},
(1, InvalidForward) => {
(0, requested_forward_scid, required),
},
(2, UnknownNextHop) => {
(0, requested_forward_scid, required),
},
(4, FailedPayment) => {
(0, payment_hash, required),
},
);
#[cfg(anchors)]
#[derive(Clone, Debug)]
pub struct AnchorDescriptor {
pub channel_keys_id: [u8; 32],
pub channel_value_satoshis: u64,
pub outpoint: OutPoint,
}
#[cfg(anchors)]
#[derive(Clone, Debug)]
pub struct HTLCDescriptor {
pub channel_keys_id: [u8; 32],
pub channel_value_satoshis: u64,
pub channel_parameters: ChannelTransactionParameters,
pub commitment_txid: Txid,
pub per_commitment_number: u64,
pub htlc: HTLCOutputInCommitment,
pub preimage: Option<PaymentPreimage>,
pub counterparty_sig: Signature
}
#[cfg(anchors)]
impl HTLCDescriptor {
pub fn unsigned_tx_input(&self) -> TxIn {
chan_utils::build_htlc_input(&self.commitment_txid, &self.htlc, true )
}
pub fn tx_output<C: secp256k1::Signing + secp256k1::Verification>(
&self, per_commitment_point: &PublicKey, secp: &Secp256k1<C>
) -> TxOut {
let channel_params = self.channel_parameters.as_holder_broadcastable();
let broadcaster_keys = channel_params.broadcaster_pubkeys();
let counterparty_keys = channel_params.countersignatory_pubkeys();
let broadcaster_delayed_key = chan_utils::derive_public_key(
secp, per_commitment_point, &broadcaster_keys.delayed_payment_basepoint
);
let counterparty_revocation_key = chan_utils::derive_public_revocation_key(
secp, per_commitment_point, &counterparty_keys.revocation_basepoint
);
chan_utils::build_htlc_output(
0 , channel_params.contest_delay(), &self.htlc, true ,
false , &broadcaster_delayed_key, &counterparty_revocation_key
)
}
pub fn witness_script<C: secp256k1::Signing + secp256k1::Verification>(
&self, per_commitment_point: &PublicKey, secp: &Secp256k1<C>
) -> Script {
let channel_params = self.channel_parameters.as_holder_broadcastable();
let broadcaster_keys = channel_params.broadcaster_pubkeys();
let counterparty_keys = channel_params.countersignatory_pubkeys();
let broadcaster_htlc_key = chan_utils::derive_public_key(
secp, per_commitment_point, &broadcaster_keys.htlc_basepoint
);
let counterparty_htlc_key = chan_utils::derive_public_key(
secp, per_commitment_point, &counterparty_keys.htlc_basepoint
);
let counterparty_revocation_key = chan_utils::derive_public_revocation_key(
secp, per_commitment_point, &counterparty_keys.revocation_basepoint
);
chan_utils::get_htlc_redeemscript_with_explicit_keys(
&self.htlc, true , &broadcaster_htlc_key, &counterparty_htlc_key,
&counterparty_revocation_key,
)
}
pub fn tx_input_witness(&self, signature: &Signature, witness_script: &Script) -> Witness {
chan_utils::build_htlc_input_witness(
signature, &self.counterparty_sig, &self.preimage, witness_script, true
)
}
}
#[cfg(anchors)]
#[derive(Clone, Debug)]
pub enum BumpTransactionEvent {
ChannelClose {
package_target_feerate_sat_per_1000_weight: u32,
commitment_tx: Transaction,
commitment_tx_fee_satoshis: u64,
anchor_descriptor: AnchorDescriptor,
pending_htlcs: Vec<HTLCOutputInCommitment>,
},
HTLCResolution {
target_feerate_sat_per_1000_weight: u32,
htlc_descriptors: Vec<HTLCDescriptor>,
},
}
enum InterceptNextHop {
FakeScid {
requested_next_hop_scid: u64,
},
}
impl_writeable_tlv_based_enum!(InterceptNextHop,
(0, FakeScid) => {
(0, requested_next_hop_scid, required),
};
);
#[derive(Clone, Debug)]
pub enum Event {
FundingGenerationReady {
temporary_channel_id: [u8; 32],
counterparty_node_id: PublicKey,
channel_value_satoshis: u64,
output_script: Script,
user_channel_id: u128,
},
PaymentClaimable {
receiver_node_id: Option<PublicKey>,
payment_hash: PaymentHash,
amount_msat: u64,
purpose: PaymentPurpose,
via_channel_id: Option<[u8; 32]>,
via_user_channel_id: Option<u128>,
},
PaymentClaimed {
receiver_node_id: Option<PublicKey>,
payment_hash: PaymentHash,
amount_msat: u64,
purpose: PaymentPurpose,
},
PaymentSent {
payment_id: Option<PaymentId>,
payment_preimage: PaymentPreimage,
payment_hash: PaymentHash,
fee_paid_msat: Option<u64>,
},
PaymentFailed {
payment_id: PaymentId,
payment_hash: PaymentHash,
},
PaymentPathSuccessful {
payment_id: PaymentId,
payment_hash: Option<PaymentHash>,
path: Vec<RouteHop>,
},
PaymentPathFailed {
payment_id: Option<PaymentId>,
payment_hash: PaymentHash,
payment_failed_permanently: bool,
network_update: Option<NetworkUpdate>,
all_paths_failed: bool,
path: Vec<RouteHop>,
short_channel_id: Option<u64>,
retry: Option<RouteParameters>,
#[cfg(test)]
error_code: Option<u16>,
#[cfg(test)]
error_data: Option<Vec<u8>>,
},
ProbeSuccessful {
payment_id: PaymentId,
payment_hash: PaymentHash,
path: Vec<RouteHop>,
},
ProbeFailed {
payment_id: PaymentId,
payment_hash: PaymentHash,
path: Vec<RouteHop>,
short_channel_id: Option<u64>,
},
PendingHTLCsForwardable {
time_forwardable: Duration,
},
HTLCIntercepted {
intercept_id: InterceptId,
requested_next_hop_scid: u64,
payment_hash: PaymentHash,
inbound_amount_msat: u64,
expected_outbound_amount_msat: u64,
},
SpendableOutputs {
outputs: Vec<SpendableOutputDescriptor>,
},
PaymentForwarded {
prev_channel_id: Option<[u8; 32]>,
next_channel_id: Option<[u8; 32]>,
fee_earned_msat: Option<u64>,
claim_from_onchain_tx: bool,
},
ChannelReady {
channel_id: [u8; 32],
user_channel_id: u128,
counterparty_node_id: PublicKey,
channel_type: ChannelTypeFeatures,
},
ChannelClosed {
channel_id: [u8; 32],
user_channel_id: u128,
reason: ClosureReason
},
DiscardFunding {
channel_id: [u8; 32],
transaction: Transaction
},
OpenChannelRequest {
temporary_channel_id: [u8; 32],
counterparty_node_id: PublicKey,
funding_satoshis: u64,
push_msat: u64,
channel_type: ChannelTypeFeatures,
},
HTLCHandlingFailed {
prev_channel_id: [u8; 32],
failed_next_destination: HTLCDestination,
},
#[cfg(anchors)]
BumpTransaction(BumpTransactionEvent),
}
impl Writeable for Event {
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
match self {
&Event::FundingGenerationReady { .. } => {
0u8.write(writer)?;
},
&Event::PaymentClaimable { ref payment_hash, ref amount_msat, ref purpose, ref receiver_node_id, ref via_channel_id, ref via_user_channel_id } => {
1u8.write(writer)?;
let mut payment_secret = None;
let payment_preimage;
match &purpose {
PaymentPurpose::InvoicePayment { payment_preimage: preimage, payment_secret: secret } => {
payment_secret = Some(secret);
payment_preimage = *preimage;
},
PaymentPurpose::SpontaneousPayment(preimage) => {
payment_preimage = Some(*preimage);
}
}
write_tlv_fields!(writer, {
(0, payment_hash, required),
(1, receiver_node_id, option),
(2, payment_secret, option),
(3, via_channel_id, option),
(4, amount_msat, required),
(5, via_user_channel_id, option),
(6, 0u64, required), (8, payment_preimage, option),
});
},
&Event::PaymentSent { ref payment_id, ref payment_preimage, ref payment_hash, ref fee_paid_msat } => {
2u8.write(writer)?;
write_tlv_fields!(writer, {
(0, payment_preimage, required),
(1, payment_hash, required),
(3, payment_id, option),
(5, fee_paid_msat, option),
});
},
&Event::PaymentPathFailed {
ref payment_id, ref payment_hash, ref payment_failed_permanently, ref network_update,
ref all_paths_failed, ref path, ref short_channel_id, ref retry,
#[cfg(test)]
ref error_code,
#[cfg(test)]
ref error_data,
} => {
3u8.write(writer)?;
#[cfg(test)]
error_code.write(writer)?;
#[cfg(test)]
error_data.write(writer)?;
write_tlv_fields!(writer, {
(0, payment_hash, required),
(1, network_update, option),
(2, payment_failed_permanently, required),
(3, all_paths_failed, required),
(5, *path, vec_type),
(7, short_channel_id, option),
(9, retry, option),
(11, payment_id, option),
});
},
&Event::PendingHTLCsForwardable { time_forwardable: _ } => {
4u8.write(writer)?;
},
&Event::SpendableOutputs { ref outputs } => {
5u8.write(writer)?;
write_tlv_fields!(writer, {
(0, WithoutLength(outputs), required),
});
},
&Event::HTLCIntercepted { requested_next_hop_scid, payment_hash, inbound_amount_msat, expected_outbound_amount_msat, intercept_id } => {
6u8.write(writer)?;
let intercept_scid = InterceptNextHop::FakeScid { requested_next_hop_scid };
write_tlv_fields!(writer, {
(0, intercept_id, required),
(2, intercept_scid, required),
(4, payment_hash, required),
(6, inbound_amount_msat, required),
(8, expected_outbound_amount_msat, required),
});
}
&Event::PaymentForwarded { fee_earned_msat, prev_channel_id, claim_from_onchain_tx, next_channel_id } => {
7u8.write(writer)?;
write_tlv_fields!(writer, {
(0, fee_earned_msat, option),
(1, prev_channel_id, option),
(2, claim_from_onchain_tx, required),
(3, next_channel_id, option),
});
},
&Event::ChannelClosed { ref channel_id, ref user_channel_id, ref reason } => {
9u8.write(writer)?;
let user_channel_id_low = *user_channel_id as u64;
let user_channel_id_high = (*user_channel_id >> 64) as u64;
write_tlv_fields!(writer, {
(0, channel_id, required),
(1, user_channel_id_low, required),
(2, reason, required),
(3, user_channel_id_high, required),
});
},
&Event::DiscardFunding { ref channel_id, ref transaction } => {
11u8.write(writer)?;
write_tlv_fields!(writer, {
(0, channel_id, required),
(2, transaction, required)
})
},
&Event::PaymentPathSuccessful { ref payment_id, ref payment_hash, ref path } => {
13u8.write(writer)?;
write_tlv_fields!(writer, {
(0, payment_id, required),
(2, payment_hash, option),
(4, *path, vec_type)
})
},
&Event::PaymentFailed { ref payment_id, ref payment_hash } => {
15u8.write(writer)?;
write_tlv_fields!(writer, {
(0, payment_id, required),
(2, payment_hash, required),
})
},
&Event::OpenChannelRequest { .. } => {
17u8.write(writer)?;
},
&Event::PaymentClaimed { ref payment_hash, ref amount_msat, ref purpose, ref receiver_node_id } => {
19u8.write(writer)?;
write_tlv_fields!(writer, {
(0, payment_hash, required),
(1, receiver_node_id, option),
(2, purpose, required),
(4, amount_msat, required),
});
},
&Event::ProbeSuccessful { ref payment_id, ref payment_hash, ref path } => {
21u8.write(writer)?;
write_tlv_fields!(writer, {
(0, payment_id, required),
(2, payment_hash, required),
(4, *path, vec_type)
})
},
&Event::ProbeFailed { ref payment_id, ref payment_hash, ref path, ref short_channel_id } => {
23u8.write(writer)?;
write_tlv_fields!(writer, {
(0, payment_id, required),
(2, payment_hash, required),
(4, *path, vec_type),
(6, short_channel_id, option),
})
},
&Event::HTLCHandlingFailed { ref prev_channel_id, ref failed_next_destination } => {
25u8.write(writer)?;
write_tlv_fields!(writer, {
(0, prev_channel_id, required),
(2, failed_next_destination, required),
})
},
#[cfg(anchors)]
&Event::BumpTransaction(ref event)=> {
27u8.write(writer)?;
match event {
BumpTransactionEvent::ChannelClose { .. } => {}
BumpTransactionEvent::HTLCResolution { .. } => {}
}
write_tlv_fields!(writer, {}); }
&Event::ChannelReady { ref channel_id, ref user_channel_id, ref counterparty_node_id, ref channel_type } => {
29u8.write(writer)?;
write_tlv_fields!(writer, {
(0, channel_id, required),
(2, user_channel_id, required),
(4, counterparty_node_id, required),
(6, channel_type, required),
});
},
}
Ok(())
}
}
impl MaybeReadable for Event {
fn read<R: io::Read>(reader: &mut R) -> Result<Option<Self>, msgs::DecodeError> {
match Readable::read(reader)? {
0u8 => Ok(None),
1u8 => {
let f = || {
let mut payment_hash = PaymentHash([0; 32]);
let mut payment_preimage = None;
let mut payment_secret = None;
let mut amount_msat = 0;
let mut receiver_node_id = None;
let mut _user_payment_id = None::<u64>; let mut via_channel_id = None;
let mut via_user_channel_id = None;
read_tlv_fields!(reader, {
(0, payment_hash, required),
(1, receiver_node_id, option),
(2, payment_secret, option),
(3, via_channel_id, option),
(4, amount_msat, required),
(5, via_user_channel_id, option),
(6, _user_payment_id, option),
(8, payment_preimage, option),
});
let purpose = match payment_secret {
Some(secret) => PaymentPurpose::InvoicePayment {
payment_preimage,
payment_secret: secret
},
None if payment_preimage.is_some() => PaymentPurpose::SpontaneousPayment(payment_preimage.unwrap()),
None => return Err(msgs::DecodeError::InvalidValue),
};
Ok(Some(Event::PaymentClaimable {
receiver_node_id,
payment_hash,
amount_msat,
purpose,
via_channel_id,
via_user_channel_id,
}))
};
f()
},
2u8 => {
let f = || {
let mut payment_preimage = PaymentPreimage([0; 32]);
let mut payment_hash = None;
let mut payment_id = None;
let mut fee_paid_msat = None;
read_tlv_fields!(reader, {
(0, payment_preimage, required),
(1, payment_hash, option),
(3, payment_id, option),
(5, fee_paid_msat, option),
});
if payment_hash.is_none() {
payment_hash = Some(PaymentHash(Sha256::hash(&payment_preimage.0[..]).into_inner()));
}
Ok(Some(Event::PaymentSent {
payment_id,
payment_preimage,
payment_hash: payment_hash.unwrap(),
fee_paid_msat,
}))
};
f()
},
3u8 => {
let f = || {
#[cfg(test)]
let error_code = Readable::read(reader)?;
#[cfg(test)]
let error_data = Readable::read(reader)?;
let mut payment_hash = PaymentHash([0; 32]);
let mut payment_failed_permanently = false;
let mut network_update = None;
let mut all_paths_failed = Some(true);
let mut path: Option<Vec<RouteHop>> = Some(vec![]);
let mut short_channel_id = None;
let mut retry = None;
let mut payment_id = None;
read_tlv_fields!(reader, {
(0, payment_hash, required),
(1, network_update, ignorable),
(2, payment_failed_permanently, required),
(3, all_paths_failed, option),
(5, path, vec_type),
(7, short_channel_id, option),
(9, retry, option),
(11, payment_id, option),
});
Ok(Some(Event::PaymentPathFailed {
payment_id,
payment_hash,
payment_failed_permanently,
network_update,
all_paths_failed: all_paths_failed.unwrap(),
path: path.unwrap(),
short_channel_id,
retry,
#[cfg(test)]
error_code,
#[cfg(test)]
error_data,
}))
};
f()
},
4u8 => Ok(None),
5u8 => {
let f = || {
let mut outputs = WithoutLength(Vec::new());
read_tlv_fields!(reader, {
(0, outputs, required),
});
Ok(Some(Event::SpendableOutputs { outputs: outputs.0 }))
};
f()
},
6u8 => {
let mut payment_hash = PaymentHash([0; 32]);
let mut intercept_id = InterceptId([0; 32]);
let mut requested_next_hop_scid = InterceptNextHop::FakeScid { requested_next_hop_scid: 0 };
let mut inbound_amount_msat = 0;
let mut expected_outbound_amount_msat = 0;
read_tlv_fields!(reader, {
(0, intercept_id, required),
(2, requested_next_hop_scid, required),
(4, payment_hash, required),
(6, inbound_amount_msat, required),
(8, expected_outbound_amount_msat, required),
});
let next_scid = match requested_next_hop_scid {
InterceptNextHop::FakeScid { requested_next_hop_scid: scid } => scid
};
Ok(Some(Event::HTLCIntercepted {
payment_hash,
requested_next_hop_scid: next_scid,
inbound_amount_msat,
expected_outbound_amount_msat,
intercept_id,
}))
},
7u8 => {
let f = || {
let mut fee_earned_msat = None;
let mut prev_channel_id = None;
let mut claim_from_onchain_tx = false;
let mut next_channel_id = None;
read_tlv_fields!(reader, {
(0, fee_earned_msat, option),
(1, prev_channel_id, option),
(2, claim_from_onchain_tx, required),
(3, next_channel_id, option),
});
Ok(Some(Event::PaymentForwarded { fee_earned_msat, prev_channel_id, claim_from_onchain_tx, next_channel_id }))
};
f()
},
9u8 => {
let f = || {
let mut channel_id = [0; 32];
let mut reason = None;
let mut user_channel_id_low_opt: Option<u64> = None;
let mut user_channel_id_high_opt: Option<u64> = None;
read_tlv_fields!(reader, {
(0, channel_id, required),
(1, user_channel_id_low_opt, option),
(2, reason, ignorable),
(3, user_channel_id_high_opt, option),
});
if reason.is_none() { return Ok(None); }
let user_channel_id = (user_channel_id_low_opt.unwrap_or(0) as u128) +
((user_channel_id_high_opt.unwrap_or(0) as u128) << 64);
Ok(Some(Event::ChannelClosed { channel_id, user_channel_id, reason: reason.unwrap() }))
};
f()
},
11u8 => {
let f = || {
let mut channel_id = [0; 32];
let mut transaction = Transaction{ version: 2, lock_time: PackedLockTime::ZERO, input: Vec::new(), output: Vec::new() };
read_tlv_fields!(reader, {
(0, channel_id, required),
(2, transaction, required),
});
Ok(Some(Event::DiscardFunding { channel_id, transaction } ))
};
f()
},
13u8 => {
let f = || {
let mut payment_id = PaymentId([0; 32]);
let mut payment_hash = None;
let mut path: Option<Vec<RouteHop>> = Some(vec![]);
read_tlv_fields!(reader, {
(0, payment_id, required),
(2, payment_hash, option),
(4, path, vec_type),
});
Ok(Some(Event::PaymentPathSuccessful {
payment_id,
payment_hash,
path: path.unwrap(),
}))
};
f()
},
15u8 => {
let f = || {
let mut payment_hash = PaymentHash([0; 32]);
let mut payment_id = PaymentId([0; 32]);
read_tlv_fields!(reader, {
(0, payment_id, required),
(2, payment_hash, required),
});
Ok(Some(Event::PaymentFailed {
payment_id,
payment_hash,
}))
};
f()
},
17u8 => {
Ok(None)
},
19u8 => {
let f = || {
let mut payment_hash = PaymentHash([0; 32]);
let mut purpose = None;
let mut amount_msat = 0;
let mut receiver_node_id = None;
read_tlv_fields!(reader, {
(0, payment_hash, required),
(1, receiver_node_id, option),
(2, purpose, ignorable),
(4, amount_msat, required),
});
if purpose.is_none() { return Ok(None); }
Ok(Some(Event::PaymentClaimed {
receiver_node_id,
payment_hash,
purpose: purpose.unwrap(),
amount_msat,
}))
};
f()
},
21u8 => {
let f = || {
let mut payment_id = PaymentId([0; 32]);
let mut payment_hash = PaymentHash([0; 32]);
let mut path: Option<Vec<RouteHop>> = Some(vec![]);
read_tlv_fields!(reader, {
(0, payment_id, required),
(2, payment_hash, required),
(4, path, vec_type),
});
Ok(Some(Event::ProbeSuccessful {
payment_id,
payment_hash,
path: path.unwrap(),
}))
};
f()
},
23u8 => {
let f = || {
let mut payment_id = PaymentId([0; 32]);
let mut payment_hash = PaymentHash([0; 32]);
let mut path: Option<Vec<RouteHop>> = Some(vec![]);
let mut short_channel_id = None;
read_tlv_fields!(reader, {
(0, payment_id, required),
(2, payment_hash, required),
(4, path, vec_type),
(6, short_channel_id, option),
});
Ok(Some(Event::ProbeFailed {
payment_id,
payment_hash,
path: path.unwrap(),
short_channel_id,
}))
};
f()
},
25u8 => {
let f = || {
let mut prev_channel_id = [0; 32];
let mut failed_next_destination_opt = None;
read_tlv_fields!(reader, {
(0, prev_channel_id, required),
(2, failed_next_destination_opt, ignorable),
});
if let Some(failed_next_destination) = failed_next_destination_opt {
Ok(Some(Event::HTLCHandlingFailed {
prev_channel_id,
failed_next_destination,
}))
} else {
Ok(None)
}
};
f()
},
27u8 => Ok(None),
29u8 => {
let f = || {
let mut channel_id = [0; 32];
let mut user_channel_id: u128 = 0;
let mut counterparty_node_id = OptionDeserWrapper(None);
let mut channel_type = OptionDeserWrapper(None);
read_tlv_fields!(reader, {
(0, channel_id, required),
(2, user_channel_id, required),
(4, counterparty_node_id, required),
(6, channel_type, required),
});
Ok(Some(Event::ChannelReady {
channel_id,
user_channel_id,
counterparty_node_id: counterparty_node_id.0.unwrap(),
channel_type: channel_type.0.unwrap()
}))
};
f()
},
x if x % 2 == 1 => {
let tlv_len: BigSize = Readable::read(reader)?;
FixedLengthReader::new(reader, tlv_len.0)
.eat_remaining().map_err(|_| msgs::DecodeError::ShortRead)?;
Ok(None)
},
_ => Err(msgs::DecodeError::InvalidValue)
}
}
}
#[derive(Clone, Debug)]
pub enum MessageSendEvent {
SendAcceptChannel {
node_id: PublicKey,
msg: msgs::AcceptChannel,
},
SendOpenChannel {
node_id: PublicKey,
msg: msgs::OpenChannel,
},
SendFundingCreated {
node_id: PublicKey,
msg: msgs::FundingCreated,
},
SendFundingSigned {
node_id: PublicKey,
msg: msgs::FundingSigned,
},
SendChannelReady {
node_id: PublicKey,
msg: msgs::ChannelReady,
},
SendAnnouncementSignatures {
node_id: PublicKey,
msg: msgs::AnnouncementSignatures,
},
UpdateHTLCs {
node_id: PublicKey,
updates: msgs::CommitmentUpdate,
},
SendRevokeAndACK {
node_id: PublicKey,
msg: msgs::RevokeAndACK,
},
SendClosingSigned {
node_id: PublicKey,
msg: msgs::ClosingSigned,
},
SendShutdown {
node_id: PublicKey,
msg: msgs::Shutdown,
},
SendChannelReestablish {
node_id: PublicKey,
msg: msgs::ChannelReestablish,
},
SendChannelAnnouncement {
node_id: PublicKey,
msg: msgs::ChannelAnnouncement,
update_msg: msgs::ChannelUpdate,
},
BroadcastChannelAnnouncement {
msg: msgs::ChannelAnnouncement,
update_msg: msgs::ChannelUpdate,
},
BroadcastChannelUpdate {
msg: msgs::ChannelUpdate,
},
SendChannelUpdate {
node_id: PublicKey,
msg: msgs::ChannelUpdate,
},
HandleError {
node_id: PublicKey,
action: msgs::ErrorAction
},
SendChannelRangeQuery {
node_id: PublicKey,
msg: msgs::QueryChannelRange,
},
SendShortIdsQuery {
node_id: PublicKey,
msg: msgs::QueryShortChannelIds,
},
SendReplyChannelRange {
node_id: PublicKey,
msg: msgs::ReplyChannelRange,
},
SendGossipTimestampFilter {
node_id: PublicKey,
msg: msgs::GossipTimestampFilter,
},
}
pub trait MessageSendEventsProvider {
fn get_and_clear_pending_msg_events(&self) -> Vec<MessageSendEvent>;
}
pub trait OnionMessageProvider {
fn next_onion_message_for_peer(&self, peer_node_id: PublicKey) -> Option<msgs::OnionMessage>;
}
pub trait EventsProvider {
fn process_pending_events<H: Deref>(&self, handler: H) where H::Target: EventHandler;
}
pub trait EventHandler {
fn handle_event(&self, event: Event);
}
impl<F> EventHandler for F where F: Fn(Event) {
fn handle_event(&self, event: Event) {
self(event)
}
}
impl<T: EventHandler> EventHandler for Arc<T> {
fn handle_event(&self, event: Event) {
self.deref().handle_event(event)
}
}