// LNP P2P library, plmeneting both bolt (BOLT) and Bifrost P2P messaging
// system for Lightning network protocol (LNP)
//
// Written in 2020-2022 by
// Dr. Maxim Orlovsky <orlovsky@pandoracore.com>
//
// To the extent possible under law, the author(s) have dedicated all
// copyright and related and neighboring rights to this software to
// the public domain worldwide. This software is distributed without
// any warranty.
//
// You should have received a copy of the MIT License
// along with this software.
// If not, see <https://opensource.org/licenses/MIT>.
mod bolt1;
mod bolt11;
mod bolt2;
mod bolt4;
mod bolt7;
mod bolt9;
mod types;
use std::io;
use std::ops::Deref;
pub use bolt1::*;
pub use bolt11::*;
pub use bolt2::*;
pub use bolt4::*;
pub use bolt7::*;
pub use bolt9::{
ChannelFeatures, Feature, FeatureContext, InitFeatures, UnknownFeatureError,
};
use internet2::{CreateUnmarshaller, Payload, Unmarshall, Unmarshaller};
use lightning_encoding::{self, LightningDecode, LightningEncode};
use once_cell::sync::Lazy;
pub use types::*;
/// Default bolt Lightning port number
pub const LNP2P_BOLT_PORT: u16 = 9735;
pub static LNP2P_LEGACY_UNMARSHALLER: Lazy<Unmarshaller<Messages>> =
Lazy::new(Messages::create_unmarshaller);
// TODO: Add unknown TLVs to all of the messages
#[derive(Clone, Debug, Display, Api)]
#[cfg_attr(feature = "strict_encoding", derive(NetworkEncode, NetworkDecode))]
#[api(encoding = "lightning")]
#[non_exhaustive]
#[display(inner)]
#[allow(clippy::large_enum_variant)]
pub enum Messages {
// Part I: Generic messages outside of channel operations (BOLT-1)
// ===============================================================
/// Once authentication is complete, the first message reveals the features
/// supported or required by this node, even if this is a reconnection.
#[api(type = 16)]
Init(Init),
/// For simplicity of diagnosis, it's often useful to tell a peer that
/// something is incorrect.
#[api(type = 17)]
Error(Error),
/// In order to allow for the existence of long-lived TCP connections, at
/// times it may be required that both ends keep alive the TCP connection
/// at the application level. Such messages also allow obfuscation of
/// traffic patterns.
#[api(type = 18)]
Ping(Ping),
/// The pong message is to be sent whenever a ping message is received. It
/// serves as a reply and also serves to keep the connection alive, while
/// explicitly notifying the other end that the receiver is still active.
/// Within the received ping message, the sender will specify the number of
/// bytes to be included within the data payload of the pong message.
#[api(type = 19)]
#[display("pong(...)")]
Pong(Vec<u8>),
// Part II: Channel management protocol (BOLT-2)
// =============================================
//
// 1. Channel establishment / closing
// ----------------------------------
/// This message contains information about a node and indicates its desire
/// to set up a new channel. This is the first step toward creating the
/// funding transaction and both versions of the commitment transaction.
#[api(type = 32)]
OpenChannel(OpenChannel),
/// This message contains information about a node and indicates its
/// acceptance of the new channel. This is the second step toward creating
/// the funding transaction and both versions of the commitment
/// transaction.
#[api(type = 33)]
AcceptChannel(AcceptChannel),
/// This message describes the outpoint which the funder has created for
/// the initial commitment transactions. After receiving the peer's
/// signature, via `funding_signed`, it will broadcast the funding
/// transaction.
#[api(type = 34)]
FundingCreated(FundingCreated),
/// This message gives the funder the signature it needs for the first
/// commitment transaction, so it can broadcast the transaction knowing
/// that funds can be redeemed, if need be.
///
/// This message introduces the `channel_id` to identify the channel.
#[api(type = 35)]
FundingSigned(FundingSigned),
/// This message indicates that the funding transaction has reached the
/// `minimum_depth` asked for in `accept_channel`. Once both nodes have
/// sent this, the channel enters normal operating mode.
#[api(type = 36)]
FundingLocked(FundingLocked),
#[api(type = 38)]
Shutdown(Shutdown),
#[api(type = 39)]
ClosingSigned(ClosingSigned),
// 2. Channel operations
// ---------------------
#[api(type = 128)]
UpdateAddHtlc(UpdateAddHtlc),
#[api(type = 130)]
UpdateFulfillHtlc(UpdateFulfillHtlc),
#[api(type = 131)]
UpdateFailHtlc(UpdateFailHtlc),
#[api(type = 135)]
UpdateFailMalformedHtlc(UpdateFailMalformedHtlc),
#[api(type = 132)]
CommitmentSigned(CommitmentSigned),
#[api(type = 133)]
RevokeAndAck(RevokeAndAck),
#[api(type = 134)]
UpdateFee(UpdateFee),
#[api(type = 136)]
ChannelReestablish(ChannelReestablish),
// Part III. Gossip protocol (BOLT-7)
// ==================================
/// This is a direct message between the two endpoints of a channel and
/// serves as an opt-in mechanism to allow the announcement of the
/// channel to the rest of the network. It contains the necessary
/// signatures, by the sender, to construct the `channel_announcement`
/// message.
#[api(type = 259)]
AnnouncementSignatures(AnnouncementSignatures),
/// This gossip message contains ownership information regarding a channel.
/// It ties each on-chain Bitcoin key to the associated Lightning node
/// key, and vice-versa. The channel is not practically usable until at
/// least one side has announced its fee levels and expiry, using
/// channel_update.
#[api(type = 256)]
ChannelAnnouncement(ChannelAnnouncement),
/// This gossip message allows a node to indicate extra data associated
/// with it, in addition to its public key. To avoid trivial denial of
/// service attacks, nodes not associated with an already known channel
/// are ignored.
#[api(type = 257)]
NodeAnnouncements(NodeAnnouncements),
/// After a channel has been initially announced, each side independently
/// announces the fees and minimum expiry delta it requires to relay HTLCs
/// through this channel. Each uses the 8-byte channel `shortid` that
/// matches the `channel_announcement` and the 1-bit `channel_flags`
/// field to indicate which end of the channel it's on (origin or
/// final). A node can do this multiple times, in order to change fees.
#[api(type = 258)]
ChannelUpdate(ChannelUpdate),
/// Extended Gossip queries
/// Negotiating the gossip_queries option via init enables a number of
/// extended queries for gossip synchronization.
#[api(type = 261)]
QueryShortChannelIds(QueryShortChannelIds),
#[api(type = 262)]
ReplyShortChannelIdsEnd(ReplyShortChannelIdsEnd),
#[api(type = 263)]
QueryChannelRange(QueryChannelRange),
#[api(type = 264)]
ReplyChannelRange(ReplyChannelRange),
#[api(type = 265)]
GossipTimestampFilter(GossipTimestampFilter),
}
impl LightningEncode for Messages {
fn lightning_encode<E: io::Write>(
&self,
e: E,
) -> Result<usize, lightning_encoding::Error> {
Payload::from(self.clone()).lightning_encode(e)
}
}
impl LightningDecode for Messages {
fn lightning_decode<D: io::Read>(
d: D,
) -> Result<Self, lightning_encoding::Error> {
let message =
LNP2P_LEGACY_UNMARSHALLER.unmarshall(d).map_err(|err| {
lightning_encoding::Error::DataIntegrityError(format!(
"can't unmarshall bolt LNP2P message. Details: {}",
err
))
})?;
Ok(message.deref().clone())
}
}