use secp256k1::key::PublicKey;
use secp256k1::Signature;
use secp256k1;
-use bitcoin::util::hash::Sha256dHash;
+use bitcoin_hashes::sha256d::Hash as Sha256dHash;
use bitcoin::blockdata::script::Script;
use std::error::Error;
}
impl LocalFeatures {
+ /// Create a blank LocalFeatures flags (visibility extended for fuzz tests)
+ #[cfg(not(feature = "fuzztarget"))]
pub(crate) fn new() -> LocalFeatures {
LocalFeatures {
- flags: Vec::new(),
+ flags: vec![2 | 1 << 5],
+ }
+ }
+ #[cfg(feature = "fuzztarget")]
+ pub fn new() -> LocalFeatures {
+ LocalFeatures {
+ flags: vec![2 | 1 << 5],
}
}
pub(crate) fn supports_data_loss_protect(&self) -> bool {
self.flags.len() > 0 && (self.flags[0] & 3) != 0
}
- pub(crate) fn requires_data_loss_protect(&self) -> bool {
- self.flags.len() > 0 && (self.flags[0] & 1) != 0
- }
-
pub(crate) fn initial_routing_sync(&self) -> bool {
self.flags.len() > 0 && (self.flags[0] & (1 << 3)) != 0
}
pub(crate) fn supports_upfront_shutdown_script(&self) -> bool {
self.flags.len() > 0 && (self.flags[0] & (3 << 4)) != 0
}
- pub(crate) fn requires_upfront_shutdown_script(&self) -> bool {
- self.flags.len() > 0 && (self.flags[0] & (1 << 4)) != 0
+ #[cfg(test)]
+ pub(crate) fn unset_upfront_shutdown_script(&mut self) {
+ self.flags[0] ^= 1 << 5;
}
pub(crate) fn requires_unknown_bits(&self) -> bool {
- for (idx, &byte) in self.flags.iter().enumerate() {
- if idx != 0 && (byte & 0x55) != 0 {
- return true;
- } else if idx == 0 && (byte & 0x14) != 0 {
- return true;
- }
- }
- return false;
+ self.flags.iter().enumerate().any(|(idx, &byte)| {
+ ( idx != 0 && (byte & 0x55) != 0 ) || ( idx == 0 && (byte & 0x14) != 0 )
+ })
}
pub(crate) fn supports_unknown_bits(&self) -> bool {
- for (idx, &byte) in self.flags.iter().enumerate() {
- if idx != 0 && byte != 0 {
- return true;
- } else if idx == 0 && (byte & 0xc4) != 0 {
- return true;
- }
- }
- return false;
+ self.flags.iter().enumerate().any(|(idx, &byte)| {
+ ( idx != 0 && byte != 0 ) || ( idx == 0 && (byte & 0xc4) != 0 )
+ })
}
}
pub(crate) contents: UnsignedChannelUpdate,
}
-/// Used to put an error message in a HandleError
+/// Used to put an error message in a LightningError
#[derive(Clone)]
pub enum ErrorAction {
/// The peer took some action which made us think they were useless. Disconnect them.
}
/// An Err type for failure to process messages.
-pub struct HandleError { //TODO: rename me
+pub struct LightningError {
/// A human-readable message describing the error
pub err: &'static str,
/// The action which should be taken against the offending peer.
- pub action: Option<ErrorAction>, //TODO: Make this required
+ pub action: ErrorAction,
}
/// Struct used to return values from revoke_and_ack messages, containing a bunch of commitment
pub trait ChannelMessageHandler : events::MessageSendEventsProvider + Send + Sync {
//Channel init:
/// Handle an incoming open_channel message from the given peer.
- fn handle_open_channel(&self, their_node_id: &PublicKey, msg: &OpenChannel) -> Result<(), HandleError>;
+ fn handle_open_channel(&self, their_node_id: &PublicKey, their_local_features: LocalFeatures, msg: &OpenChannel) -> Result<(), LightningError>;
/// Handle an incoming accept_channel message from the given peer.
- fn handle_accept_channel(&self, their_node_id: &PublicKey, msg: &AcceptChannel) -> Result<(), HandleError>;
+ fn handle_accept_channel(&self, their_node_id: &PublicKey, their_local_features: LocalFeatures, msg: &AcceptChannel) -> Result<(), LightningError>;
/// Handle an incoming funding_created message from the given peer.
- fn handle_funding_created(&self, their_node_id: &PublicKey, msg: &FundingCreated) -> Result<(), HandleError>;
+ fn handle_funding_created(&self, their_node_id: &PublicKey, msg: &FundingCreated) -> Result<(), LightningError>;
/// Handle an incoming funding_signed message from the given peer.
- fn handle_funding_signed(&self, their_node_id: &PublicKey, msg: &FundingSigned) -> Result<(), HandleError>;
+ fn handle_funding_signed(&self, their_node_id: &PublicKey, msg: &FundingSigned) -> Result<(), LightningError>;
/// Handle an incoming funding_locked message from the given peer.
- fn handle_funding_locked(&self, their_node_id: &PublicKey, msg: &FundingLocked) -> Result<(), HandleError>;
+ fn handle_funding_locked(&self, their_node_id: &PublicKey, msg: &FundingLocked) -> Result<(), LightningError>;
// Channl close:
/// Handle an incoming shutdown message from the given peer.
- fn handle_shutdown(&self, their_node_id: &PublicKey, msg: &Shutdown) -> Result<(), HandleError>;
+ fn handle_shutdown(&self, their_node_id: &PublicKey, msg: &Shutdown) -> Result<(), LightningError>;
/// Handle an incoming closing_signed message from the given peer.
- fn handle_closing_signed(&self, their_node_id: &PublicKey, msg: &ClosingSigned) -> Result<(), HandleError>;
+ fn handle_closing_signed(&self, their_node_id: &PublicKey, msg: &ClosingSigned) -> Result<(), LightningError>;
// HTLC handling:
/// Handle an incoming update_add_htlc message from the given peer.
- fn handle_update_add_htlc(&self, their_node_id: &PublicKey, msg: &UpdateAddHTLC) -> Result<(), HandleError>;
+ fn handle_update_add_htlc(&self, their_node_id: &PublicKey, msg: &UpdateAddHTLC) -> Result<(), LightningError>;
/// Handle an incoming update_fulfill_htlc message from the given peer.
- fn handle_update_fulfill_htlc(&self, their_node_id: &PublicKey, msg: &UpdateFulfillHTLC) -> Result<(), HandleError>;
+ fn handle_update_fulfill_htlc(&self, their_node_id: &PublicKey, msg: &UpdateFulfillHTLC) -> Result<(), LightningError>;
/// Handle an incoming update_fail_htlc message from the given peer.
- fn handle_update_fail_htlc(&self, their_node_id: &PublicKey, msg: &UpdateFailHTLC) -> Result<(), HandleError>;
+ fn handle_update_fail_htlc(&self, their_node_id: &PublicKey, msg: &UpdateFailHTLC) -> Result<(), LightningError>;
/// Handle an incoming update_fail_malformed_htlc message from the given peer.
- fn handle_update_fail_malformed_htlc(&self, their_node_id: &PublicKey, msg: &UpdateFailMalformedHTLC) -> Result<(), HandleError>;
+ fn handle_update_fail_malformed_htlc(&self, their_node_id: &PublicKey, msg: &UpdateFailMalformedHTLC) -> Result<(), LightningError>;
/// Handle an incoming commitment_signed message from the given peer.
- fn handle_commitment_signed(&self, their_node_id: &PublicKey, msg: &CommitmentSigned) -> Result<(), HandleError>;
+ fn handle_commitment_signed(&self, their_node_id: &PublicKey, msg: &CommitmentSigned) -> Result<(), LightningError>;
/// Handle an incoming revoke_and_ack message from the given peer.
- fn handle_revoke_and_ack(&self, their_node_id: &PublicKey, msg: &RevokeAndACK) -> Result<(), HandleError>;
+ fn handle_revoke_and_ack(&self, their_node_id: &PublicKey, msg: &RevokeAndACK) -> Result<(), LightningError>;
/// Handle an incoming update_fee message from the given peer.
- fn handle_update_fee(&self, their_node_id: &PublicKey, msg: &UpdateFee) -> Result<(), HandleError>;
+ fn handle_update_fee(&self, their_node_id: &PublicKey, msg: &UpdateFee) -> Result<(), LightningError>;
// Channel-to-announce:
/// Handle an incoming announcement_signatures message from the given peer.
- fn handle_announcement_signatures(&self, their_node_id: &PublicKey, msg: &AnnouncementSignatures) -> Result<(), HandleError>;
+ fn handle_announcement_signatures(&self, their_node_id: &PublicKey, msg: &AnnouncementSignatures) -> Result<(), LightningError>;
// Connection loss/reestablish:
/// Indicates a connection to the peer failed/an existing connection was lost. If no connection
/// Handle a peer reconnecting, possibly generating channel_reestablish message(s).
fn peer_connected(&self, their_node_id: &PublicKey);
/// Handle an incoming channel_reestablish message from the given peer.
- fn handle_channel_reestablish(&self, their_node_id: &PublicKey, msg: &ChannelReestablish) -> Result<(), HandleError>;
+ fn handle_channel_reestablish(&self, their_node_id: &PublicKey, msg: &ChannelReestablish) -> Result<(), LightningError>;
// Error:
/// Handle an incoming error message from the given peer.
pub trait RoutingMessageHandler : Send + Sync {
/// Handle an incoming node_announcement message, returning true if it should be forwarded on,
/// false or returning an Err otherwise.
- fn handle_node_announcement(&self, msg: &NodeAnnouncement) -> Result<bool, HandleError>;
+ fn handle_node_announcement(&self, msg: &NodeAnnouncement) -> Result<bool, LightningError>;
/// Handle a channel_announcement message, returning true if it should be forwarded on, false
/// or returning an Err otherwise.
- fn handle_channel_announcement(&self, msg: &ChannelAnnouncement) -> Result<bool, HandleError>;
+ fn handle_channel_announcement(&self, msg: &ChannelAnnouncement) -> Result<bool, LightningError>;
/// Handle an incoming channel_update message, returning true if it should be forwarded on,
/// false or returning an Err otherwise.
- fn handle_channel_update(&self, msg: &ChannelUpdate) -> Result<bool, HandleError>;
+ fn handle_channel_update(&self, msg: &ChannelUpdate) -> Result<bool, LightningError>;
/// Handle some updates to the route graph that we learned due to an outbound failed payment.
fn handle_htlc_fail_channel_update(&self, update: &HTLCFailChannelUpdate);
/// Gets a subset of the channel announcements and updates required to dump our routing table
pub(crate) data: OnionRealm0HopData,
pub(crate) hmac: [u8; 32],
}
- unsafe impl ::util::internal_traits::NoDealloc for OnionHopData{}
pub struct DecodedOnionErrorPacket {
pub(crate) hmac: [u8; 32],
}
}
-impl fmt::Debug for HandleError {
+impl fmt::Debug for LightningError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str(self.err)
}
mod tests {
use hex;
use ln::msgs;
- use ln::msgs::{GlobalFeatures, OptionalField, OnionErrorPacket};
+ use ln::msgs::{GlobalFeatures, LocalFeatures, OptionalField, OnionErrorPacket};
use ln::channelmanager::{PaymentPreimage, PaymentHash};
use util::ser::Writeable;
- use bitcoin::util::hash::Sha256dHash;
+ use bitcoin_hashes::sha256d::Hash as Sha256dHash;
+ use bitcoin_hashes::hex::FromHex;
use bitcoin::util::address::Address;
use bitcoin::network::constants::Network;
use bitcoin::blockdata::script::Builder;
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(&pubkey_1, Network::Testnet).script_pubkey()) } else { OptionalField::Absent }
+ shutdown_scriptpubkey: if shutdown { OptionalField::Present(Address::p2pkh(&::bitcoin::PublicKey{compressed: true, key: pubkey_1}, Network::Testnet).script_pubkey()) } else { OptionalField::Absent }
};
let encoded_value = open_channel.encode();
let mut target_value = Vec::new();
delayed_payment_basepoint: pubkey_4,
htlc_basepoint: pubkey_5,
first_per_commitment_point: pubkey_6,
- shutdown_scriptpubkey: if shutdown { OptionalField::Present(Address::p2pkh(&pubkey_1, Network::Testnet).script_pubkey()) } else { OptionalField::Absent }
+ shutdown_scriptpubkey: if shutdown { OptionalField::Present(Address::p2pkh(&::bitcoin::PublicKey{compressed: true, key: pubkey_1}, Network::Testnet).script_pubkey()) } else { OptionalField::Absent }
};
let encoded_value = accept_channel.encode();
let mut target_value = hex::decode("020202020202020202020202020202020202020202020202020202020202020212345678901234562334032891223698321446687011447600083a840000034d000c89d4c0bcc0bc031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f024d4b6cd1361032ca9bd2aeb9d900aa4d45d9ead80ac9423374c451a7254d076602531fe6068134503d2723133227c867ac8fa6c83c537e9a44c3c5bdbdcb1fe33703462779ad4aad39514614751a71085f2f10e1c7a593e4e030efb5b8721ce55b0b0362c0a046dacce86ddd0343c6d3c7c79c2208ba0d9c9cf24a6d046d21d21f90f703f006a18d5653c4edf5391ff23a61f03ff83d237e880ee61187fa9f379a028e0a").unwrap();
let script = Builder::new().push_opcode(opcodes::OP_TRUE).into_script();
let shutdown = msgs::Shutdown {
channel_id: [2; 32],
- scriptpubkey: if script_type == 1 { Address::p2pkh(&pubkey_1, Network::Testnet).script_pubkey() } else if script_type == 2 { Address::p2sh(&script, Network::Testnet).script_pubkey() } else if script_type == 3 { Address::p2wpkh(&pubkey_1, Network::Testnet).script_pubkey() } else { Address::p2wsh(&script, Network::Testnet).script_pubkey() },
+ scriptpubkey: if script_type == 1 { Address::p2pkh(&::bitcoin::PublicKey{compressed: true, key: pubkey_1}, Network::Testnet).script_pubkey() } else if script_type == 2 { Address::p2sh(&script, Network::Testnet).script_pubkey() } else if script_type == 3 { Address::p2wpkh(&::bitcoin::PublicKey{compressed: true, key: pubkey_1}, Network::Testnet).script_pubkey() } else { Address::p2wsh(&script, Network::Testnet).script_pubkey() },
};
let encoded_value = shutdown.encode();
let mut target_value = hex::decode("0202020202020202020202020202020202020202020202020202020202020202").unwrap();
let target_value = hex::decode("0202020202020202020202020202020202020202020202020202020202020202013413a7").unwrap();
assert_eq!(encoded_value, target_value);
}
+
+ fn do_encoding_init(unknown_global_bits: bool, initial_routing_sync: bool) {
+ let mut global = GlobalFeatures::new();
+ if unknown_global_bits {
+ global.flags = vec![0xFF, 0xFF];
+ }
+ let mut local = LocalFeatures::new();
+ if initial_routing_sync {
+ local.set_initial_routing_sync();
+ }
+ let init = msgs::Init {
+ global_features: global,
+ local_features: local,
+ };
+ let encoded_value = init.encode();
+ let mut target_value = Vec::new();
+ if unknown_global_bits {
+ target_value.append(&mut hex::decode("0002ffff").unwrap());
+ } else {
+ target_value.append(&mut hex::decode("0000").unwrap());
+ }
+ if initial_routing_sync {
+ target_value.append(&mut hex::decode("00012a").unwrap());
+ } else {
+ target_value.append(&mut hex::decode("000122").unwrap());
+ }
+ assert_eq!(encoded_value, target_value);
+ }
+
+ #[test]
+ fn encoding_init() {
+ do_encoding_init(false, false);
+ do_encoding_init(true, false);
+ do_encoding_init(false, true);
+ do_encoding_init(true, true);
+ }
+
+ #[test]
+ fn encoding_error() {
+ let error = msgs::ErrorMessage {
+ channel_id: [2; 32],
+ data: String::from("rust-lightning"),
+ };
+ let encoded_value = error.encode();
+ let target_value = hex::decode("0202020202020202020202020202020202020202020202020202020202020202000e727573742d6c696768746e696e67").unwrap();
+ assert_eq!(encoded_value, target_value);
+ }
+
+ #[test]
+ fn encoding_ping() {
+ let ping = msgs::Ping {
+ ponglen: 64,
+ byteslen: 64
+ };
+ let encoded_value = ping.encode();
+ let target_value = hex::decode("0040004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").unwrap();
+ assert_eq!(encoded_value, target_value);
+ }
+
+ #[test]
+ fn encoding_pong() {
+ let pong = msgs::Pong {
+ byteslen: 64
+ };
+ let encoded_value = pong.encode();
+ let target_value = hex::decode("004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").unwrap();
+ assert_eq!(encoded_value, target_value);
+ }
}