use bitcoin::hash_types::Txid;
use crate::blinded_path::payment::{BlindedPaymentTlvs, ForwardTlvs, ReceiveTlvs};
-use crate::ln::{ChannelId, PaymentPreimage, PaymentHash, PaymentSecret};
+use crate::ln::types::{ChannelId, PaymentPreimage, PaymentHash, PaymentSecret};
use crate::ln::features::{ChannelFeatures, ChannelTypeFeatures, InitFeatures, NodeFeatures};
use crate::ln::onion_utils;
use crate::onion_message;
use crate::events::{EventsProvider, MessageSendEventsProvider};
use crate::crypto::streams::ChaChaPolyReadAdapter;
use crate::util::logger;
-use crate::util::ser::{LengthReadable, LengthReadableArgs, Readable, ReadableArgs, Writeable, Writer, WithoutLength, FixedLengthReader, HighZeroBytesDroppedBigSize, Hostname, TransactionU16LenLimited, BigSize};
+use crate::util::ser::{BigSize, FixedLengthReader, HighZeroBytesDroppedBigSize, Hostname, LengthRead, LengthReadable, LengthReadableArgs, Readable, ReadableArgs, TransactionU16LenLimited, WithoutLength, Writeable, Writer};
use crate::util::base32;
use crate::routing::gossip::{NodeAlias, NodeId};
pub tx_hash: Txid,
/// The list of witnesses
pub witnesses: Vec<Witness>,
+ /// Optional signature for the shared input -- the previous funding outpoint -- signed by both peers
+ pub funding_outpoint_sig: Option<Signature>,
}
/// A tx_init_rbf message which initiates a replacement of the transaction after it's been
// Splicing
/// Handle an incoming `splice` message from the given peer.
+ #[cfg(splicing)]
fn handle_splice(&self, their_node_id: &PublicKey, msg: &Splice);
/// Handle an incoming `splice_ack` message from the given peer.
+ #[cfg(splicing)]
fn handle_splice_ack(&self, their_node_id: &PublicKey, msg: &SpliceAck);
/// Handle an incoming `splice_locked` message from the given peer.
+ #[cfg(splicing)]
fn handle_splice_locked(&self, their_node_id: &PublicKey, msg: &SpliceLocked);
// Interactive channel construction
mod fuzzy_internal_msgs {
use bitcoin::secp256k1::PublicKey;
use crate::blinded_path::payment::{PaymentConstraints, PaymentContext, PaymentRelay};
- use crate::ln::{PaymentPreimage, PaymentSecret};
+ use crate::ln::types::{PaymentPreimage, PaymentSecret};
use crate::ln::features::BlindedHopFeatures;
use super::{FinalOnionHopData, TrampolineOnionPacket};
}
}
- pub(crate) enum OutboundOnionPayload {
+ pub(crate) enum OutboundOnionPayload<'a> {
Forward {
short_channel_id: u64,
/// The value, in msat, of the payment after this hop's fee is deducted.
},
Receive {
payment_data: Option<FinalOnionHopData>,
- payment_metadata: Option<Vec<u8>>,
+ payment_metadata: Option<&'a Vec<u8>>,
keysend_preimage: Option<PaymentPreimage>,
- custom_tlvs: Vec<(u64, Vec<u8>)>,
+ custom_tlvs: &'a Vec<(u64, Vec<u8>)>,
sender_intended_htlc_amt_msat: u64,
cltv_expiry_height: u32,
},
BlindedForward {
- encrypted_tlvs: Vec<u8>,
+ encrypted_tlvs: &'a Vec<u8>,
intro_node_blinding_point: Option<PublicKey>,
},
BlindedReceive {
sender_intended_htlc_amt_msat: u64,
total_msat: u64,
cltv_expiry_height: u32,
- encrypted_tlvs: Vec<u8>,
+ encrypted_tlvs: &'a Vec<u8>,
intro_node_blinding_point: Option<PublicKey>, // Set if the introduction node of the blinded path is the final node
keysend_preimage: Option<PaymentPreimage>,
- custom_tlvs: Vec<(u64, Vec<u8>)>,
+ custom_tlvs: &'a Vec<(u64, Vec<u8>)>,
}
}
}
}
+impl LengthReadable for TrampolineOnionPacket {
+ fn read<R: LengthRead>(r: &mut R) -> Result<Self, DecodeError> {
+ let version = Readable::read(r)?;
+ let public_key = Readable::read(r)?;
+
+ let hop_data_len = r.total_bytes().saturating_sub(66); // 1 (version) + 33 (pubkey) + 32 (HMAC) = 66
+ let mut rd = FixedLengthReader::new(r, hop_data_len);
+ let hop_data = WithoutLength::<Vec<u8>>::read(&mut rd)?.0;
+
+ let hmac = Readable::read(r)?;
+
+ Ok(TrampolineOnionPacket {
+ version,
+ public_key,
+ hop_data,
+ hmac,
+ })
+ }
+}
+
impl Debug for TrampolineOnionPacket {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_fmt(format_args!("TrampolineOnionPacket version {} with hmac {:?}", self.version, &self.hmac[..]))
channel_id,
tx_hash,
witnesses,
-}, {});
+}, {
+ (0, funding_outpoint_sig, option),
+});
impl_writeable_msg!(TxInitRbf, {
channel_id,
}
}
-impl Writeable for OutboundOnionPayload {
+impl<'a> Writeable for OutboundOnionPayload<'a> {
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
match self {
Self::Forward { short_channel_id, amt_to_forward, outgoing_cltv_value } => {
(2, HighZeroBytesDroppedBigSize(*sender_intended_htlc_amt_msat), required),
(4, HighZeroBytesDroppedBigSize(*cltv_expiry_height), required),
(8, payment_data, option),
- (16, payment_metadata.as_ref().map(|m| WithoutLength(m)), option)
+ (16, payment_metadata.map(|m| WithoutLength(m)), option)
}, custom_tlvs.iter());
},
Self::BlindedForward { encrypted_tlvs, intro_node_blinding_point } => {
_encode_varint_length_prefixed_tlv!(w, {
- (10, *encrypted_tlvs, required_vec),
+ (10, **encrypted_tlvs, required_vec),
(12, intro_node_blinding_point, option)
});
},
_encode_varint_length_prefixed_tlv!(w, {
(2, HighZeroBytesDroppedBigSize(*sender_intended_htlc_amt_msat), required),
(4, HighZeroBytesDroppedBigSize(*cltv_expiry_height), required),
- (10, *encrypted_tlvs, required_vec),
+ (10, **encrypted_tlvs, required_vec),
(12, intro_node_blinding_point, option),
(18, HighZeroBytesDroppedBigSize(*total_msat), required)
}, custom_tlvs.iter());
#[cfg(test)]
mod tests {
- use bitcoin::{Transaction, TxIn, ScriptBuf, Sequence, Witness, TxOut};
+ use bitcoin::{Amount, Transaction, TxIn, ScriptBuf, Sequence, Witness, TxOut};
use hex::DisplayHex;
- use crate::ln::{PaymentPreimage, PaymentHash, PaymentSecret};
- use crate::ln::ChannelId;
+ use crate::ln::types::{ChannelId, PaymentPreimage, PaymentHash, PaymentSecret};
use crate::ln::features::{ChannelFeatures, ChannelTypeFeatures, InitFeatures, NodeFeatures};
use crate::ln::msgs::{self, FinalOnionHopData, OnionErrorPacket, CommonOpenChannelFields, CommonAcceptChannelFields, TrampolineOnionPacket};
use crate::ln::msgs::SocketAddress;
use crate::routing::gossip::{NodeAlias, NodeId};
- use crate::util::ser::{BigSize, Hostname, Readable, ReadableArgs, TransactionU16LenLimited, Writeable};
+ use crate::util::ser::{BigSize, FixedLengthReader, Hostname, LengthReadable, Readable, ReadableArgs, TransactionU16LenLimited, Writeable};
use crate::util::test_utils;
use bitcoin::hashes::hex::FromHex;
use bitcoin::address::Address;
- use bitcoin::network::constants::Network;
+ use bitcoin::network::Network;
use bitcoin::blockdata::constants::ChainHash;
use bitcoin::blockdata::script::Builder;
use bitcoin::blockdata::opcodes;
use bitcoin::hash_types::Txid;
use bitcoin::locktime::absolute::LockTime;
+ use bitcoin::transaction::Version;
use bitcoin::secp256k1::{PublicKey,SecretKey};
use bitcoin::secp256k1::{Secp256k1, Message};
macro_rules! get_sig_on {
($privkey: expr, $ctx: expr, $string: expr) => {
{
- let sighash = Message::from_slice(&$string.into_bytes()[..]).unwrap();
+ let sighash = Message::from_digest_slice(&$string.into_bytes()[..]).unwrap();
$ctx.sign_ecdsa(&sighash, &$privkey)
}
}
channel_id: ChannelId::from_bytes([2; 32]),
serial_id: 4886718345,
prevtx: TransactionU16LenLimited::new(Transaction {
- version: 2,
+ version: Version::TWO,
lock_time: LockTime::ZERO,
input: vec![TxIn {
previous_output: OutPoint { txid: Txid::from_str("305bab643ee297b8b6b76b320792c8223d55082122cb606bf89382146ced9c77").unwrap(), index: 2 }.into_bitcoin_outpoint(),
}],
output: vec![
TxOut {
- value: 12704566,
- script_pubkey: Address::from_str("bc1qzlffunw52jav8vwdu5x3jfk6sr8u22rmq3xzw2").unwrap().payload.script_pubkey(),
+ value: Amount::from_sat(12704566),
+ script_pubkey: Address::from_str("bc1qzlffunw52jav8vwdu5x3jfk6sr8u22rmq3xzw2").unwrap().payload().script_pubkey(),
},
TxOut {
- value: 245148,
- script_pubkey: Address::from_str("bc1qxmk834g5marzm227dgqvynd23y2nvt2ztwcw2z").unwrap().payload.script_pubkey(),
+ value: Amount::from_sat(245148),
+ script_pubkey: Address::from_str("bc1qxmk834g5marzm227dgqvynd23y2nvt2ztwcw2z").unwrap().payload().script_pubkey(),
},
],
}).unwrap(),
channel_id: ChannelId::from_bytes([2; 32]),
serial_id: 4886718345,
sats: 4886718345,
- script: Address::from_str("bc1qxmk834g5marzm227dgqvynd23y2nvt2ztwcw2z").unwrap().payload.script_pubkey(),
+ script: Address::from_str("bc1qxmk834g5marzm227dgqvynd23y2nvt2ztwcw2z").unwrap().payload().script_pubkey(),
};
let encoded_value = tx_add_output.encode();
let target_value = <Vec<u8>>::from_hex("0202020202020202020202020202020202020202020202020202020202020202000000012345678900000001234567890016001436ec78d514df462da95e6a00c24daa8915362d42").unwrap();
#[test]
fn encoding_tx_signatures() {
+ let secp_ctx = Secp256k1::new();
+ let (privkey_1, _) = get_keys_from!("0101010101010101010101010101010101010101010101010101010101010101", secp_ctx);
+ let sig_1 = get_sig_on!(privkey_1, secp_ctx, String::from("01010101010101010101010101010101"));
+
let tx_signatures = msgs::TxSignatures {
channel_id: ChannelId::from_bytes([2; 32]),
tx_hash: Txid::from_str("c2d4449afa8d26140898dd54d3390b057ba2a5afcf03ba29d7dc0d8b9ffe966e").unwrap(),
<Vec<u8>>::from_hex("3045022100ee00dbf4a862463e837d7c08509de814d620e4d9830fa84818713e0fa358f145022021c3c7060c4d53fe84fd165d60208451108a778c13b92ca4c6bad439236126cc01").unwrap(),
<Vec<u8>>::from_hex("028fbbf0b16f5ba5bcb5dd37cd4047ce6f726a21c06682f9ec2f52b057de1dbdb5").unwrap()]),
],
+ funding_outpoint_sig: Some(sig_1),
};
let encoded_value = tx_signatures.encode();
let mut target_value = <Vec<u8>>::from_hex("0202020202020202020202020202020202020202020202020202020202020202").unwrap(); // channel_id
target_value.append(&mut <Vec<u8>>::from_hex("3045022100ee00dbf4a862463e837d7c08509de814d620e4d9830fa84818713e0fa358f145022021c3c7060c4d53fe84fd165d60208451108a778c13b92ca4c6bad439236126cc01").unwrap());
target_value.append(&mut <Vec<u8>>::from_hex("21").unwrap()); // len of witness element data (VarInt)
target_value.append(&mut <Vec<u8>>::from_hex("028fbbf0b16f5ba5bcb5dd37cd4047ce6f726a21c06682f9ec2f52b057de1dbdb5").unwrap());
+ target_value.append(&mut <Vec<u8>>::from_hex("0040").unwrap()); // type and len (64)
+ target_value.append(&mut <Vec<u8>>::from_hex("d977cb9b53d93a6ff64bb5f1e158b4094b66e798fb12911168a3ccdf80a83096340a6a95da0ae8d9f776528eecdbb747eb6b545495a4319ed5378e35b21e073a").unwrap());
assert_eq!(encoded_value, target_value);
}
keysend_preimage: None,
sender_intended_htlc_amt_msat: 0x0badf00d01020304,
cltv_expiry_height: 0xffffffff,
- custom_tlvs: vec![],
+ custom_tlvs: &vec![],
};
let encoded_value = outbound_msg.encode();
let target_value = <Vec<u8>>::from_hex("1002080badf00d010203040404ffffffff").unwrap();
keysend_preimage: None,
sender_intended_htlc_amt_msat: 0x0badf00d01020304,
cltv_expiry_height: 0xffffffff,
- custom_tlvs: vec![],
+ custom_tlvs: &vec![],
};
let encoded_value = outbound_msg.encode();
let target_value = <Vec<u8>>::from_hex("3602080badf00d010203040404ffffffff082442424242424242424242424242424242424242424242424242424242424242421badca1f").unwrap();
payment_data: None,
payment_metadata: None,
keysend_preimage: None,
- custom_tlvs: bad_type_range_tlvs,
+ custom_tlvs: &bad_type_range_tlvs,
sender_intended_htlc_amt_msat: 0x0badf00d01020304,
cltv_expiry_height: 0xffffffff,
};
((1 << 16) - 1, vec![42; 32]),
];
if let msgs::OutboundOnionPayload::Receive { ref mut custom_tlvs, .. } = msg {
- *custom_tlvs = good_type_range_tlvs.clone();
+ *custom_tlvs = &good_type_range_tlvs;
}
let encoded_value = msg.encode();
let inbound_msg = ReadableArgs::read(&mut Cursor::new(&encoded_value[..]), (None, &&node_signer)).unwrap();
payment_data: None,
payment_metadata: None,
keysend_preimage: None,
- custom_tlvs: expected_custom_tlvs.clone(),
+ custom_tlvs: &expected_custom_tlvs,
sender_intended_htlc_amt_msat: 0x0badf00d01020304,
cltv_expiry_height: 0xffffffff,
};
let encoded_trampoline_packet = trampoline_packet.encode();
assert_eq!(encoded_trampoline_packet.len(), 716);
+ { // verify that a codec round trip works
+ let mut reader = Cursor::new(&encoded_trampoline_packet);
+ let mut trampoline_packet_reader = FixedLengthReader::new(&mut reader, encoded_trampoline_packet.len() as u64);
+ let decoded_trampoline_packet: TrampolineOnionPacket = <TrampolineOnionPacket as LengthReadable>::read(&mut trampoline_packet_reader).unwrap();
+ assert_eq!(decoded_trampoline_packet.encode(), encoded_trampoline_packet);
+ }
+
let msg = msgs::OutboundOnionPayload::TrampolineEntrypoint {
multipath_trampoline_data: None,
amt_to_forward: 0x0badf00d01020304,