use crate::events::{MessageSendEventsProvider, OnionMessageProvider};
use crate::util::logger;
-use crate::util::ser::{LengthReadable, Readable, ReadableArgs, Writeable, Writer, FixedLengthReader, HighZeroBytesDroppedBigSize, Hostname};
+use crate::util::ser::{LengthReadable, Readable, ReadableArgs, Writeable, Writer, WithoutLength, FixedLengthReader, HighZeroBytesDroppedBigSize, Hostname};
use crate::ln::{PaymentPreimage, PaymentHash, PaymentSecret};
-use crate::routing::gossip::NodeId;
+use crate::routing::gossip::{NodeAlias, NodeId};
/// 21 million * 10^8 * 1000
pub(crate) const MAX_VALUE_MSAT: u64 = 21_000_000_0000_0000_000;
pub first_per_commitment_point: PublicKey,
/// The channel flags to be used
pub channel_flags: u8,
- /// Optionally, a request to pre-set the to-sender output's `scriptPubkey` for when we collaboratively close
- pub shutdown_scriptpubkey: OptionalField<Script>,
+ /// A request to pre-set the to-sender output's `scriptPubkey` for when we collaboratively close
+ pub shutdown_scriptpubkey: Option<Script>,
/// The channel type that this channel will represent
///
/// If this is `None`, we derive the channel type from the intersection of our
pub htlc_basepoint: PublicKey,
/// The first to-be-broadcast-by-sender transaction's per commitment point
pub first_per_commitment_point: PublicKey,
- /// Optionally, a request to pre-set the to-sender output's scriptPubkey for when we collaboratively close
- pub shutdown_scriptpubkey: OptionalField<Script>,
+ /// A request to pre-set the to-sender output's scriptPubkey for when we collaboratively close
+ pub shutdown_scriptpubkey: Option<Script>,
/// The channel type that this channel will represent.
///
/// If this is `None`, we derive the channel type from the intersection of
pub channel_id: [u8; 32],
/// The signature of the channel acceptor (fundee) on the initial commitment transaction
pub signature: Signature,
+ #[cfg(taproot)]
+ /// The partial signature of the channel acceptor (fundee)
+ pub partial_signature_with_nonce: Option<PartialSignatureWithNonce>,
}
/// A [`channel_ready`] message to be sent to or received from a peer.
pub signature: Signature,
/// Signatures on the HTLC transactions
pub htlc_signatures: Vec<Signature>,
+ #[cfg(taproot)]
+ /// The partial Taproot signature on the commitment transaction
+ pub partial_signature_with_nonce: Option<PartialSignatureWithNonce>,
}
/// A [`revoke_and_ack`] message to be sent to or received from a peer.
pub per_commitment_secret: [u8; 32],
/// The next sender-broadcast commitment transaction's per-commitment point
pub next_per_commitment_point: PublicKey,
+ #[cfg(taproot)]
+ /// Musig nonce the recipient should use in their next commitment signature message
+ pub next_local_nonce: Option<musig2::types::PublicNonce>
}
/// An [`update_fee`] message to be sent to or received from a peer
pub feerate_per_kw: u32,
}
-#[derive(Clone, Debug, PartialEq, Eq)]
-/// Proof that the sender knows the per-commitment secret of the previous commitment transaction.
-///
-/// This is used to convince the recipient that the channel is at a certain commitment
-/// number even if they lost that data due to a local failure. Of course, the peer may lie
-/// and even later commitments may have been revoked.
-pub struct DataLossProtect {
- /// Proof that the sender knows the per-commitment secret of a specific commitment transaction
- /// belonging to the recipient
- pub your_last_per_commitment_secret: [u8; 32],
- /// The sender's per-commitment point for their current commitment transaction
- pub my_current_per_commitment_point: PublicKey,
-}
-
/// A [`channel_reestablish`] message to be sent to or received from a peer.
///
/// [`channel_reestablish`]: https://github.com/lightning/bolts/blob/master/02-peer-protocol.md#message-retransmission
pub next_local_commitment_number: u64,
/// The next commitment number for the recipient
pub next_remote_commitment_number: u64,
- /// Optionally, a field proving that next_remote_commitment_number-1 has been revoked
- pub data_loss_protect: OptionalField<DataLossProtect>,
+ /// Proof that the sender knows the per-commitment secret of a specific commitment transaction
+ /// belonging to the recipient
+ pub your_last_per_commitment_secret: [u8; 32],
+ /// The sender's per-commitment point for their current commitment transaction
+ pub my_current_per_commitment_point: PublicKey,
}
/// An [`announcement_signatures`] message to be sent to or received from a peer.
/// An alias, for UI purposes.
///
/// This should be sanitized before use. There is no guarantee of uniqueness.
- pub alias: [u8; 32],
+ pub alias: NodeAlias,
/// List of addresses on which this node is reachable
pub addresses: Vec<NetAddress>,
pub(crate) excess_address_data: Vec<u8>,
pub commitment_signed: CommitmentSigned,
}
-/// Messages could have optional fields to use with extended features
-/// As we wish to serialize these differently from `Option<T>`s (`Options` get a tag byte, but
-/// [`OptionalField`] simply gets `Present` if there are enough bytes to read into it), we have a
-/// separate enum type for them.
-///
-/// This is not exported to bindings users due to a free generic in `T`
-#[derive(Clone, Debug, PartialEq, Eq)]
-pub enum OptionalField<T> {
- /// Optional field is included in message
- Present(T),
- /// Optional field is absent in message
- Absent
-}
-
/// A trait to describe an object which can receive channel messages.
///
/// Messages MAY be called in parallel when they originate from different `their_node_ids`, however
},
FinalNode {
payment_data: Option<FinalOnionHopData>,
+ payment_metadata: Option<Vec<u8>>,
keysend_preimage: Option<PaymentPreimage>,
},
}
}
}
-impl Writeable for OptionalField<Script> {
- fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
- match *self {
- OptionalField::Present(ref script) => {
- // Note that Writeable for script includes the 16-bit length tag for us
- script.write(w)?;
- },
- OptionalField::Absent => {}
- }
- Ok(())
- }
-}
-
-impl Readable for OptionalField<Script> {
- fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
- match <u16 as Readable>::read(r) {
- Ok(len) => {
- let mut buf = vec![0; len as usize];
- r.read_exact(&mut buf)?;
- Ok(OptionalField::Present(Script::from(buf)))
- },
- Err(DecodeError::ShortRead) => Ok(OptionalField::Absent),
- Err(e) => Err(e)
- }
- }
-}
-
-impl Writeable for OptionalField<u64> {
- fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
- match *self {
- OptionalField::Present(ref value) => {
- value.write(w)?;
- },
- OptionalField::Absent => {}
- }
- Ok(())
- }
-}
-
-impl Readable for OptionalField<u64> {
- fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
- let value: u64 = Readable::read(r)?;
- Ok(OptionalField::Present(value))
- }
-}
-
#[cfg(not(taproot))]
impl_writeable_msg!(AcceptChannel, {
temporary_channel_id,
delayed_payment_basepoint,
htlc_basepoint,
first_per_commitment_point,
- shutdown_scriptpubkey
}, {
+ (0, shutdown_scriptpubkey, (option, encoding: (Script, WithoutLength))), // Don't encode length twice.
(1, channel_type, option),
});
delayed_payment_basepoint,
htlc_basepoint,
first_per_commitment_point,
- shutdown_scriptpubkey
}, {
+ (0, shutdown_scriptpubkey, (option, encoding: (Script, WithoutLength))), // Don't encode length twice.
(1, channel_type, option),
(4, next_local_nonce, option),
});
bitcoin_signature
}, {});
-impl Writeable for ChannelReestablish {
- fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
- self.channel_id.write(w)?;
- self.next_local_commitment_number.write(w)?;
- self.next_remote_commitment_number.write(w)?;
- match self.data_loss_protect {
- OptionalField::Present(ref data_loss_protect) => {
- (*data_loss_protect).your_last_per_commitment_secret.write(w)?;
- (*data_loss_protect).my_current_per_commitment_point.write(w)?;
- },
- OptionalField::Absent => {}
- }
- Ok(())
- }
-}
-
-impl Readable for ChannelReestablish{
- fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
- Ok(Self {
- channel_id: Readable::read(r)?,
- next_local_commitment_number: Readable::read(r)?,
- next_remote_commitment_number: Readable::read(r)?,
- data_loss_protect: {
- match <[u8; 32] as Readable>::read(r) {
- Ok(your_last_per_commitment_secret) =>
- OptionalField::Present(DataLossProtect {
- your_last_per_commitment_secret,
- my_current_per_commitment_point: Readable::read(r)?,
- }),
- Err(DecodeError::ShortRead) => OptionalField::Absent,
- Err(e) => return Err(e)
- }
- }
- })
- }
-}
+impl_writeable_msg!(ChannelReestablish, {
+ channel_id,
+ next_local_commitment_number,
+ next_remote_commitment_number,
+ your_last_per_commitment_secret,
+ my_current_per_commitment_point,
+}, {});
impl_writeable_msg!(ClosingSigned,
{ channel_id, fee_satoshis, signature },
max_fee_satoshis
});
+#[cfg(not(taproot))]
impl_writeable_msg!(CommitmentSigned, {
channel_id,
signature,
htlc_signatures
}, {});
+#[cfg(taproot)]
+impl_writeable_msg!(CommitmentSigned, {
+ channel_id,
+ signature,
+ htlc_signatures
+}, {
+ (2, partial_signature_with_nonce, option)
+});
+
impl_writeable!(DecodedOnionErrorPacket, {
hmac,
failuremsg,
(4, next_local_nonce, option)
});
+#[cfg(not(taproot))]
impl_writeable_msg!(FundingSigned, {
channel_id,
signature
}, {});
+#[cfg(taproot)]
+impl_writeable_msg!(FundingSigned, {
+ channel_id,
+ signature
+}, {
+ (2, partial_signature_with_nonce, option)
+});
+
impl_writeable_msg!(ChannelReady, {
channel_id,
next_per_commitment_point,
(3, remote_network_address, option)
});
Ok(Init {
- features: features.or(global_features),
+ features: features | global_features,
remote_network_address,
})
}
htlc_basepoint,
first_per_commitment_point,
channel_flags,
- shutdown_scriptpubkey
}, {
+ (0, shutdown_scriptpubkey, (option, encoding: (Script, WithoutLength))), // Don't encode length twice.
(1, channel_type, option),
});
+#[cfg(not(taproot))]
impl_writeable_msg!(RevokeAndACK, {
channel_id,
per_commitment_secret,
next_per_commitment_point
}, {});
+#[cfg(taproot)]
+impl_writeable_msg!(RevokeAndACK, {
+ channel_id,
+ per_commitment_secret,
+ next_per_commitment_point
+}, {
+ (4, next_local_nonce, option)
+});
+
impl_writeable_msg!(Shutdown, {
channel_id,
scriptpubkey
(6, short_channel_id, required)
});
},
- OnionHopDataFormat::FinalNode { ref payment_data, ref keysend_preimage } => {
+ OnionHopDataFormat::FinalNode { ref payment_data, ref payment_metadata, ref keysend_preimage } => {
_encode_varint_length_prefixed_tlv!(w, {
(2, HighZeroBytesDroppedBigSize(self.amt_to_forward), required),
(4, HighZeroBytesDroppedBigSize(self.outgoing_cltv_value), required),
(8, payment_data, option),
+ (16, payment_metadata.as_ref().map(|m| WithoutLength(m)), option),
(5482373484, keysend_preimage, option)
});
},
let mut cltv_value = HighZeroBytesDroppedBigSize(0u32);
let mut short_id: Option<u64> = None;
let mut payment_data: Option<FinalOnionHopData> = None;
+ let mut payment_metadata: Option<WithoutLength<Vec<u8>>> = None;
let mut keysend_preimage: Option<PaymentPreimage> = None;
read_tlv_fields!(r, {
(2, amt, required),
(4, cltv_value, required),
(6, short_id, option),
(8, payment_data, option),
+ (16, payment_metadata, option),
// See https://github.com/lightning/blips/blob/master/blip-0003.md
(5482373484, keysend_preimage, option)
});
let format = if let Some(short_channel_id) = short_id {
if payment_data.is_some() { return Err(DecodeError::InvalidValue); }
+ if payment_metadata.is_some() { return Err(DecodeError::InvalidValue); }
OnionHopDataFormat::NonFinalNode {
short_channel_id,
}
} else {
- if let &Some(ref data) = &payment_data {
+ if let Some(data) = &payment_data {
if data.total_msat > MAX_VALUE_MSAT {
return Err(DecodeError::InvalidValue);
}
}
OnionHopDataFormat::FinalNode {
payment_data,
+ payment_metadata: payment_metadata.map(|w| w.0),
keysend_preimage,
}
};
let node_id: NodeId = Readable::read(r)?;
let mut rgb = [0; 3];
r.read_exact(&mut rgb)?;
- let alias: [u8; 32] = Readable::read(r)?;
+ let alias: NodeAlias = Readable::read(r)?;
let addr_len: u16 = Readable::read(r)?;
let mut addresses: Vec<NetAddress> = Vec::new();
use crate::ln::{PaymentPreimage, PaymentHash, PaymentSecret};
use crate::ln::features::{ChannelFeatures, ChannelTypeFeatures, InitFeatures, NodeFeatures};
use crate::ln::msgs;
- use crate::ln::msgs::{FinalOnionHopData, OptionalField, OnionErrorPacket, OnionHopDataFormat};
- use crate::routing::gossip::NodeId;
+ use crate::ln::msgs::{FinalOnionHopData, OnionErrorPacket, OnionHopDataFormat};
+ use crate::routing::gossip::{NodeAlias, NodeId};
use crate::util::ser::{Writeable, Readable, Hostname};
use bitcoin::hashes::hex::FromHex;
use core::convert::TryFrom;
#[test]
- fn encoding_channel_reestablish_no_secret() {
- let cr = msgs::ChannelReestablish {
- channel_id: [4, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0],
- next_local_commitment_number: 3,
- next_remote_commitment_number: 4,
- data_loss_protect: OptionalField::Absent,
- };
-
- let encoded_value = cr.encode();
- assert_eq!(
- encoded_value,
- vec![4, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4]
- );
- }
-
- #[test]
- fn encoding_channel_reestablish_with_secret() {
+ fn encoding_channel_reestablish() {
let public_key = {
let secp_ctx = Secp256k1::new();
PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&hex::decode("0101010101010101010101010101010101010101010101010101010101010101").unwrap()[..]).unwrap())
channel_id: [4, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0],
next_local_commitment_number: 3,
next_remote_commitment_number: 4,
- data_loss_protect: OptionalField::Present(msgs::DataLossProtect { your_last_per_commitment_secret: [9;32], my_current_per_commitment_point: public_key}),
+ your_last_per_commitment_secret: [9;32],
+ my_current_per_commitment_point: public_key,
};
let encoded_value = cr.encode();
timestamp: 20190119,
node_id: NodeId::from_pubkey(&pubkey_1),
rgb: [32; 3],
- alias: [16;32],
+ alias: NodeAlias([16;32]),
addresses,
excess_address_data: if excess_address_data { vec![33, 108, 40, 11, 83, 149, 162, 84, 110, 126, 75, 38, 99, 224, 79, 129, 22, 34, 241, 90, 79, 146, 232, 58, 162, 233, 43, 162, 165, 115, 193, 57, 20, 44, 84, 174, 99, 7, 42, 30, 193, 238, 125, 192, 192, 75, 222, 92, 132, 120, 6, 23, 42, 160, 92, 146, 194, 42, 232, 227, 8, 209, 210, 105] } else { Vec::new() },
excess_data: if excess_data { vec![59, 18, 204, 25, 92, 224, 162, 209, 189, 166, 168, 139, 239, 161, 159, 160, 127, 81, 202, 167, 92, 232, 56, 55, 242, 137, 101, 96, 11, 138, 172, 171, 8, 85, 255, 176, 231, 65, 236, 95, 124, 65, 66, 30, 152, 41, 169, 212, 134, 17, 200, 200, 49, 247, 27, 229, 234, 115, 230, 101, 148, 151, 127, 253] } else { Vec::new() },
htlc_basepoint: pubkey_5,
first_per_commitment_point: pubkey_6,
channel_flags: if random_bit { 1 << 5 } else { 0 },
- shutdown_scriptpubkey: if shutdown { OptionalField::Present(Address::p2pkh(&::bitcoin::PublicKey{compressed: true, inner: pubkey_1}, Network::Testnet).script_pubkey()) } else { OptionalField::Absent },
+ shutdown_scriptpubkey: if shutdown { Some(Address::p2pkh(&::bitcoin::PublicKey{compressed: true, inner: pubkey_1}, Network::Testnet).script_pubkey()) } else { None },
channel_type: if incl_chan_type { Some(ChannelTypeFeatures::empty()) } else { None },
};
let encoded_value = open_channel.encode();
delayed_payment_basepoint: pubkey_4,
htlc_basepoint: pubkey_5,
first_per_commitment_point: pubkey_6,
- shutdown_scriptpubkey: if shutdown { OptionalField::Present(Address::p2pkh(&::bitcoin::PublicKey{compressed: true, inner: pubkey_1}, Network::Testnet).script_pubkey()) } else { OptionalField::Absent },
+ shutdown_scriptpubkey: if shutdown { Some(Address::p2pkh(&::bitcoin::PublicKey{compressed: true, inner: pubkey_1}, Network::Testnet).script_pubkey()) } else { None },
channel_type: None,
#[cfg(taproot)]
next_local_nonce: None,
let funding_signed = msgs::FundingSigned {
channel_id: [2; 32],
signature: sig_1,
+ #[cfg(taproot)]
+ partial_signature_with_nonce: None,
};
let encoded_value = funding_signed.encode();
let target_value = hex::decode("0202020202020202020202020202020202020202020202020202020202020202d977cb9b53d93a6ff64bb5f1e158b4094b66e798fb12911168a3ccdf80a83096340a6a95da0ae8d9f776528eecdbb747eb6b545495a4319ed5378e35b21e073a").unwrap();
channel_id: [2; 32],
signature: sig_1,
htlc_signatures: if htlcs { vec![sig_2, sig_3, sig_4] } else { Vec::new() },
+ #[cfg(taproot)]
+ partial_signature_with_nonce: None,
};
let encoded_value = commitment_signed.encode();
let mut target_value = hex::decode("0202020202020202020202020202020202020202020202020202020202020202d977cb9b53d93a6ff64bb5f1e158b4094b66e798fb12911168a3ccdf80a83096340a6a95da0ae8d9f776528eecdbb747eb6b545495a4319ed5378e35b21e073a").unwrap();
channel_id: [2; 32],
per_commitment_secret: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
next_per_commitment_point: pubkey_1,
+ #[cfg(taproot)]
+ next_local_nonce: None,
};
let encoded_value = raa.encode();
let target_value = hex::decode("02020202020202020202020202020202020202020202020202020202020202020101010101010101010101010101010101010101010101010101010101010101031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f").unwrap();
let mut msg = msgs::OnionHopData {
format: OnionHopDataFormat::FinalNode {
payment_data: None,
+ payment_metadata: None,
keysend_preimage: None,
},
amt_to_forward: 0x0badf00d01020304,
payment_secret: expected_payment_secret,
total_msat: 0x1badca1f
}),
+ payment_metadata: None,
keysend_preimage: None,
},
amt_to_forward: 0x0badf00d01020304,
payment_secret,
total_msat: 0x1badca1f
}),
+ payment_metadata: None,
keysend_preimage: None,
} = msg.format {
assert_eq!(payment_secret, expected_payment_secret);