use prelude::*;
use core::{cmp, fmt};
use core::fmt::Debug;
-use std::io::Read;
+use io::{self, Read};
+use io_extras::read_to_end;
use util::events::MessageSendEventsProvider;
use util::logger;
BadLengthDescriptor,
/// Error from std::io
Io(/// (C-not exported) as ErrorKind doesn't have a reasonable mapping
- ::std::io::ErrorKind),
+ io::ErrorKind),
/// The message included zlib-compressed values, which we don't support.
UnsupportedCompression,
}
pub funding_txid: Txid,
/// The specific output index funding this channel
pub funding_output_index: u16,
- /// The signature of the channel initiator (funder) on the funding transaction
+ /// The signature of the channel initiator (funder) on the initial commitment transaction
pub signature: Signature,
}
pub struct FundingSigned {
/// The channel ID
pub channel_id: [u8; 32],
- /// The signature of the channel acceptor (fundee) on the funding transaction
+ /// The signature of the channel acceptor (fundee) on the initial commitment transaction
pub signature: Signature,
}
pub scriptpubkey: Script,
}
+/// The minimum and maximum fees which the sender is willing to place on the closing transaction.
+/// This is provided in [`ClosingSigned`] by both sides to indicate the fee range they are willing
+/// to use.
+#[derive(Clone, Debug, PartialEq)]
+pub struct ClosingSignedFeeRange {
+ /// The minimum absolute fee, in satoshis, which the sender is willing to place on the closing
+ /// transaction.
+ pub min_fee_satoshis: u64,
+ /// The maximum absolute fee, in satoshis, which the sender is willing to place on the closing
+ /// transaction.
+ pub max_fee_satoshis: u64,
+}
+
/// A closing_signed message to be sent or received from a peer
#[derive(Clone, Debug, PartialEq)]
pub struct ClosingSigned {
pub fee_satoshis: u64,
/// A signature on the closing transaction
pub signature: Signature,
+ /// The minimum and maximum fees which the sender is willing to accept, provided only by new
+ /// nodes.
+ pub fee_range: Option<ClosingSignedFeeRange>,
}
/// An update_add_htlc message to be sent or received from a peer
}
impl Writeable for NetAddress {
- fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
+ fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
match self {
&NetAddress::IPv4 { ref addr, ref port } => {
1u8.write(writer)?;
}
}
-impl From<::std::io::Error> for DecodeError {
- fn from(e: ::std::io::Error) -> Self {
- if e.kind() == ::std::io::ErrorKind::UnexpectedEof {
+impl From<io::Error> for DecodeError {
+ fn from(e: io::Error) -> Self {
+ if e.kind() == io::ErrorKind::UnexpectedEof {
DecodeError::ShortRead
} else {
DecodeError::Io(e.kind())
}
impl Writeable for OptionalField<Script> {
- fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
+ 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
}
impl Writeable for OptionalField<u64> {
- fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
+ fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
match *self {
OptionalField::Present(ref value) => {
value.write(w)?;
});
impl Writeable for ChannelReestablish {
- fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
+ fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
w.size_hint(if let OptionalField::Present(..) = self.data_loss_protect { 32+2*8+33+32 } else { 32+2*8 });
self.channel_id.write(w)?;
self.next_local_commitment_number.write(w)?;
}
}
-impl_writeable!(ClosingSigned, 32+8+64, {
- channel_id,
- fee_satoshis,
- signature
+impl Writeable for ClosingSigned {
+ fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
+ w.size_hint(32 + 8 + 64 + if self.fee_range.is_some() { 1+1+ 2*8 } else { 0 });
+ self.channel_id.write(w)?;
+ self.fee_satoshis.write(w)?;
+ self.signature.write(w)?;
+ encode_tlv_stream!(w, {
+ (1, self.fee_range, option),
+ });
+ Ok(())
+ }
+}
+
+impl Readable for ClosingSigned {
+ fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
+ let channel_id = Readable::read(r)?;
+ let fee_satoshis = Readable::read(r)?;
+ let signature = Readable::read(r)?;
+ let mut fee_range = None;
+ decode_tlv_stream!(r, {
+ (1, fee_range, option),
+ });
+ Ok(Self { channel_id, fee_satoshis, signature, fee_range })
+ }
+}
+
+impl_writeable!(ClosingSignedFeeRange, 2*8, {
+ min_fee_satoshis,
+ max_fee_satoshis
});
impl_writeable_len_match!(CommitmentSigned, {
});
impl Writeable for Init {
- fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
+ fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
// global_features gets the bottom 13 bits of our features, and local_features gets all of
// our relevant feature bits. This keeps us compatible with old nodes.
self.features.write_up_to_13(w)?;
});
impl Writeable for OnionPacket {
- fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
+ fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
w.size_hint(1 + 33 + 20*65 + 32);
self.version.write(w)?;
match self.public_key {
});
impl Writeable for FinalOnionHopData {
- fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
+ fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
w.size_hint(32 + 8 - (self.total_msat.leading_zeros()/8) as usize);
self.payment_secret.0.write(w)?;
HighZeroBytesDroppedVarInt(self.total_msat).write(w)
}
impl Writeable for OnionHopData {
- fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
+ fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
w.size_hint(33);
// Note that this should never be reachable if Rust-Lightning generated the message, as we
// check values are sane long before we get here, though its possible in the future
}
impl Writeable for Ping {
- fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
+ fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
w.size_hint(self.byteslen as usize + 4);
self.ponglen.write(w)?;
vec![0u8; self.byteslen as usize].write(w)?; // size-unchecked write
}
impl Writeable for Pong {
- fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
+ fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
w.size_hint(self.byteslen as usize + 2);
vec![0u8; self.byteslen as usize].write(w)?; // size-unchecked write
Ok(())
}
impl Writeable for UnsignedChannelAnnouncement {
- fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
+ fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
w.size_hint(2 + 32 + 8 + 4*33 + self.features.byte_count() + self.excess_data.len());
self.features.write(w)?;
self.chain_hash.write(w)?;
node_id_2: Readable::read(r)?,
bitcoin_key_1: Readable::read(r)?,
bitcoin_key_2: Readable::read(r)?,
- excess_data: {
- let mut excess_data = vec![];
- r.read_to_end(&mut excess_data)?;
- excess_data
- },
+ excess_data: read_to_end(r)?,
})
}
}
});
impl Writeable for UnsignedChannelUpdate {
- fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
+ fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
let mut size = 64 + self.excess_data.len();
let mut message_flags: u8 = 0;
if let OptionalField::Present(_) = self.htlc_maximum_msat {
fee_base_msat: Readable::read(r)?,
fee_proportional_millionths: Readable::read(r)?,
htlc_maximum_msat: if has_htlc_maximum_msat { Readable::read(r)? } else { OptionalField::Absent },
- excess_data: {
- let mut excess_data = vec![];
- r.read_to_end(&mut excess_data)?;
- excess_data
- },
+ excess_data: read_to_end(r)?,
})
}
}
});
impl Writeable for ErrorMessage {
- fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
+ fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
w.size_hint(32 + 2 + self.data.len());
self.channel_id.write(w)?;
(self.data.len() as u16).write(w)?;
channel_id: Readable::read(r)?,
data: {
let mut sz: usize = <u16 as Readable>::read(r)? as usize;
- let mut data = vec![];
- let data_len = r.read_to_end(&mut data)?;
- sz = cmp::min(data_len, sz);
+ let data = read_to_end(r)?;
+ sz = cmp::min(data.len(), sz);
match String::from_utf8(data[..sz as usize].to_vec()) {
Ok(s) => s,
Err(_) => return Err(DecodeError::InvalidValue),
}
impl Writeable for UnsignedNodeAnnouncement {
- fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
+ fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
w.size_hint(76 + self.features.byte_count() + self.addresses.len()*38 + self.excess_address_data.len() + self.excess_data.len());
self.features.write(w)?;
self.timestamp.write(w)?;
}
Vec::new()
};
- r.read_to_end(&mut excess_data)?;
+ excess_data.extend(read_to_end(r)?.iter());
Ok(UnsignedNodeAnnouncement {
features,
timestamp,
}
impl Writeable for QueryShortChannelIds {
- fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
+ fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
// Calculated from 1-byte encoding_type plus 8-bytes per short_channel_id
let encoding_len: u16 = 1 + self.short_channel_ids.len() as u16 * 8;
}
impl Writeable for ReplyShortChannelIdsEnd {
- fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
+ fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
w.size_hint(32 + 1);
self.chain_hash.write(w)?;
self.full_information.write(w)?;
}
impl Writeable for QueryChannelRange {
- fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
+ fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
w.size_hint(32 + 4 + 4);
self.chain_hash.write(w)?;
self.first_blocknum.write(w)?;
}
impl Writeable for ReplyChannelRange {
- fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
+ fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
let encoding_len: u16 = 1 + self.short_channel_ids.len() as u16 * 8;
w.size_hint(32 + 4 + 4 + 1 + 2 + encoding_len as usize);
self.chain_hash.write(w)?;
}
impl Writeable for GossipTimestampFilter {
- fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
+ fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
w.size_hint(32 + 4 + 4);
self.chain_hash.write(w)?;
self.first_timestamp.write(w)?;
use bitcoin::secp256k1::key::{PublicKey,SecretKey};
use bitcoin::secp256k1::{Secp256k1, Message};
+ use io::Cursor;
use prelude::*;
- use std::io::Cursor;
#[test]
fn encoding_channel_reestablish_no_secret() {
channel_id: [2; 32],
fee_satoshis: 2316138423780173,
signature: sig_1,
+ fee_range: None,
};
let encoded_value = closing_signed.encode();
let target_value = hex::decode("020202020202020202020202020202020202020202020202020202020202020200083a840000034dd977cb9b53d93a6ff64bb5f1e158b4094b66e798fb12911168a3ccdf80a83096340a6a95da0ae8d9f776528eecdbb747eb6b545495a4319ed5378e35b21e073a").unwrap();
assert_eq!(encoded_value, target_value);
+ assert_eq!(msgs::ClosingSigned::read(&mut Cursor::new(&target_value)).unwrap(), closing_signed);
+
+ let closing_signed_with_range = msgs::ClosingSigned {
+ channel_id: [2; 32],
+ fee_satoshis: 2316138423780173,
+ signature: sig_1,
+ fee_range: Some(msgs::ClosingSignedFeeRange {
+ min_fee_satoshis: 0xdeadbeef,
+ max_fee_satoshis: 0x1badcafe01234567,
+ }),
+ };
+ let encoded_value_with_range = closing_signed_with_range.encode();
+ let target_value_with_range = hex::decode("020202020202020202020202020202020202020202020202020202020202020200083a840000034dd977cb9b53d93a6ff64bb5f1e158b4094b66e798fb12911168a3ccdf80a83096340a6a95da0ae8d9f776528eecdbb747eb6b545495a4319ed5378e35b21e073a011000000000deadbeef1badcafe01234567").unwrap();
+ assert_eq!(encoded_value_with_range, target_value_with_range);
+ assert_eq!(msgs::ClosingSigned::read(&mut Cursor::new(&target_value_with_range)).unwrap(),
+ closing_signed_with_range);
}
#[test]