/// appears.
pub struct Features<T: FeatureContext> {
#[cfg(not(test))]
+ /// Note that, for convinience, flags is LITTLE endian (despite being big-endian on the wire)
flags: Vec<u8>,
// Used to test encoding of diverse msgs
#[cfg(test)]
pub type ChannelFeatures = Features<FeatureContextChannel>;
impl<T: FeatureContextInitNode> Features<T> {
- /// Create a blank Features flags (visibility extended for fuzz tests)
+ /// Create a Features with the features we support
#[cfg(not(feature = "fuzztarget"))]
- pub(crate) fn new() -> Features<T> {
+ pub(crate) fn supported() -> Features<T> {
Features {
flags: vec![2 | 1 << 5],
mark: PhantomData,
}
}
#[cfg(feature = "fuzztarget")]
- pub fn new() -> Features<T> {
+ pub fn supported() -> Features<T> {
Features {
flags: vec![2 | 1 << 5],
mark: PhantomData,
}
impl Features<FeatureContextChannel> {
- /// Create a blank Features flags (visibility extended for fuzz tests)
+ /// Create a Features with the features we support
#[cfg(not(feature = "fuzztarget"))]
- pub(crate) fn new() -> Features<FeatureContextChannel> {
+ pub(crate) fn supported() -> Features<FeatureContextChannel> {
Features {
flags: Vec::new(),
mark: PhantomData,
}
}
#[cfg(feature = "fuzztarget")]
- pub fn new() -> Features<FeatureContextChannel> {
+ pub fn supported() -> Features<FeatureContextChannel> {
Features {
flags: Vec::new(),
mark: PhantomData,
}
impl<T: FeatureContext> Features<T> {
+ /// Create a blank Features with no fetures set
+ pub fn empty() -> Features<T> {
+ Features {
+ flags: Vec::new(),
+ mark: PhantomData,
+ }
+ }
+
pub(crate) fn requires_unknown_bits(&self) -> bool {
self.flags.iter().enumerate().any(|(idx, &byte)| {
( idx != 0 && (byte & 0x55) != 0 ) || ( idx == 0 && (byte & 0x14) != 0 )
impl<T: FeatureContext> Writeable for Features<T> {
fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
w.size_hint(self.flags.len() + 2);
- self.flags.write(w)
+ (self.flags.len() as u16).write(w)?;
+ for f in self.flags.iter().rev() { // We have to swap the endianness back to BE for writing
+ f.write(w)?;
+ }
+ Ok(())
}
}
impl<R: ::std::io::Read, T: FeatureContext> Readable<R> for Features<T> {
fn read(r: &mut R) -> Result<Self, DecodeError> {
+ let mut flags: Vec<u8> = Readable::read(r)?;
+ flags.reverse(); // Swap to big-endian
Ok(Self {
- flags: Readable::read(r)?,
+ flags,
mark: PhantomData,
})
}
}
+
/// An init message to be sent or received from a peer
pub struct Init {
pub(crate) features: InitFeatures,
let sig_2 = get_sig_on!(privkey_2, secp_ctx, String::from("01010101010101010101010101010101"));
let sig_3 = get_sig_on!(privkey_3, secp_ctx, String::from("01010101010101010101010101010101"));
let sig_4 = get_sig_on!(privkey_4, secp_ctx, String::from("01010101010101010101010101010101"));
- let mut features = ChannelFeatures::new();
+ let mut features = ChannelFeatures::supported();
if unknown_features_bits {
features.flags = vec![0xFF, 0xFF];
}
let secp_ctx = Secp256k1::new();
let (privkey_1, pubkey_1) = get_keys_from!("0101010101010101010101010101010101010101010101010101010101010101", secp_ctx);
let sig_1 = get_sig_on!(privkey_1, secp_ctx, String::from("01010101010101010101010101010101"));
- let mut features = NodeFeatures::new();
+ let mut features = NodeFeatures::empty();
if unknown_features_bits {
features.flags = vec![0xFF, 0xFF];
+ } else {
+ // Set to some features we may support
+ features.flags = vec![2 | 1 << 5];
}
let mut addresses = Vec::new();
if ipv4 {