Make Inventory and NetworkMessage enums exhaustive
Both by added an `Unknown` variant.
This commit is contained in:
parent
944371d6a2
commit
767b14f696
|
@ -80,12 +80,6 @@ pub enum Error {
|
|||
ParseFailed(&'static str),
|
||||
/// Unsupported Segwit flag
|
||||
UnsupportedSegwitFlag(u8),
|
||||
/// Unrecognized network command with its length
|
||||
UnrecognizedNetworkCommand(String, usize),
|
||||
/// Invalid Inventory type
|
||||
UnknownInventoryType(u32),
|
||||
/// The network command is longer than the maximum allowed (12 chars)
|
||||
NetworkCommandTooLong(String),
|
||||
}
|
||||
|
||||
impl fmt::Display for Error {
|
||||
|
@ -104,10 +98,6 @@ impl fmt::Display for Error {
|
|||
Error::ParseFailed(ref e) => write!(f, "parse failed: {}", e),
|
||||
Error::UnsupportedSegwitFlag(ref swflag) => write!(f,
|
||||
"unsupported segwit version: {}", swflag),
|
||||
Error::UnrecognizedNetworkCommand(ref nwcmd, _) => write!(f,
|
||||
"unrecognized network command: {}", nwcmd),
|
||||
Error::UnknownInventoryType(ref tp) => write!(f, "Unknown Inventory type: {}", tp),
|
||||
Error::NetworkCommandTooLong(ref cmd) => write!(f, "Network Command too long: {}", cmd),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -123,10 +113,7 @@ impl error::Error for Error {
|
|||
| Error::NonMinimalVarInt
|
||||
| Error::UnknownNetworkMagic(..)
|
||||
| Error::ParseFailed(..)
|
||||
| Error::UnsupportedSegwitFlag(..)
|
||||
| Error::UnrecognizedNetworkCommand(..)
|
||||
| Error::UnknownInventoryType(..)
|
||||
| Error::NetworkCommandTooLong(..) => None,
|
||||
| Error::UnsupportedSegwitFlag(..) => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -109,9 +109,9 @@ pub struct RawNetworkMessage {
|
|||
pub payload: NetworkMessage
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
/// A Network message payload. Proper documentation is available on at
|
||||
/// [Bitcoin Wiki: Protocol Specification](https://en.bitcoin.it/wiki/Protocol_specification)
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
pub enum NetworkMessage {
|
||||
/// `version`
|
||||
Version(message_network::VersionMessage),
|
||||
|
@ -173,10 +173,22 @@ pub enum NetworkMessage {
|
|||
AddrV2(Vec<AddrV2Message>),
|
||||
/// `sendaddrv2`
|
||||
SendAddrV2,
|
||||
|
||||
/// Any other message.
|
||||
Unknown {
|
||||
/// The command of this message.
|
||||
command: CommandString,
|
||||
/// The payload of this message.
|
||||
payload: Vec<u8>,
|
||||
}
|
||||
}
|
||||
|
||||
impl NetworkMessage {
|
||||
/// Return the message command. This is useful for debug outputs.
|
||||
/// Return the message command as a static string reference.
|
||||
///
|
||||
/// This returns `"unknown"` for [NetworkMessage::Unknown],
|
||||
/// regardless of the actual command in the unknown message.
|
||||
/// Use the [command] method to get the command for unknown messages.
|
||||
pub fn cmd(&self) -> &'static str {
|
||||
match *self {
|
||||
NetworkMessage::Version(_) => "version",
|
||||
|
@ -207,17 +219,25 @@ impl NetworkMessage {
|
|||
NetworkMessage::WtxidRelay => "wtxidrelay",
|
||||
NetworkMessage::AddrV2(_) => "addrv2",
|
||||
NetworkMessage::SendAddrV2 => "sendaddrv2",
|
||||
NetworkMessage::Unknown { .. } => "unknown",
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the CommandString for the message command.
|
||||
pub fn command(&self) -> CommandString {
|
||||
CommandString::try_from(self.cmd()).expect("cmd returns valid commands")
|
||||
match *self {
|
||||
NetworkMessage::Unknown { command: ref c, .. } => c.clone(),
|
||||
_ => CommandString::try_from(self.cmd()).expect("cmd returns valid commands")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl RawNetworkMessage {
|
||||
/// Return the message command. This is useful for debug outputs.
|
||||
/// Return the message command as a static string reference.
|
||||
///
|
||||
/// This returns `"unknown"` for [NetworkMessage::Unknown],
|
||||
/// regardless of the actual command in the unknown message.
|
||||
/// Use the [command] method to get the command for unknown messages.
|
||||
pub fn cmd(&self) -> &'static str {
|
||||
self.payload.cmd()
|
||||
}
|
||||
|
@ -281,8 +301,9 @@ impl Encodable for RawNetworkMessage {
|
|||
| NetworkMessage::SendHeaders
|
||||
| NetworkMessage::MemPool
|
||||
| NetworkMessage::GetAddr
|
||||
| NetworkMessage::WtxidRelay => vec![],
|
||||
| NetworkMessage::WtxidRelay
|
||||
| NetworkMessage::SendAddrV2 => vec![],
|
||||
NetworkMessage::Unknown { payload: ref data, .. } => serialize(data),
|
||||
}).consensus_encode(&mut s)?;
|
||||
Ok(len)
|
||||
}
|
||||
|
@ -314,12 +335,11 @@ impl Decodable for HeaderDeserializationWrapper {
|
|||
impl Decodable for RawNetworkMessage {
|
||||
fn consensus_decode<D: io::Read>(mut d: D) -> Result<Self, encode::Error> {
|
||||
let magic = Decodable::consensus_decode(&mut d)?;
|
||||
let cmd = CommandString::consensus_decode(&mut d)?.0;
|
||||
let cmd = CommandString::consensus_decode(&mut d)?;
|
||||
let raw_payload = CheckedData::consensus_decode(&mut d)?.0;
|
||||
let raw_payload_len = raw_payload.len();
|
||||
|
||||
let mut mem_d = Cursor::new(raw_payload);
|
||||
let payload = match &cmd[..] {
|
||||
let payload = match &cmd.0[..] {
|
||||
"version" => NetworkMessage::Version(Decodable::consensus_decode(&mut mem_d)?),
|
||||
"verack" => NetworkMessage::Verack,
|
||||
"addr" => NetworkMessage::Addr(Decodable::consensus_decode(&mut mem_d)?),
|
||||
|
@ -350,7 +370,10 @@ impl Decodable for RawNetworkMessage {
|
|||
"wtxidrelay" => NetworkMessage::WtxidRelay,
|
||||
"addrv2" => NetworkMessage::AddrV2(Decodable::consensus_decode(&mut mem_d)?),
|
||||
"sendaddrv2" => NetworkMessage::SendAddrV2,
|
||||
_ => return Err(encode::Error::UnrecognizedNetworkCommand(cmd.into_owned(), 4 + 12 + 4 + 4 + raw_payload_len)), // magic + msg str + payload len + checksum + payload
|
||||
_ => NetworkMessage::Unknown {
|
||||
command: cmd,
|
||||
payload: mem_d.into_inner(),
|
||||
}
|
||||
};
|
||||
Ok(RawNetworkMessage {
|
||||
magic: magic,
|
||||
|
|
|
@ -41,6 +41,13 @@ pub enum Inventory {
|
|||
WitnessTransaction(Txid),
|
||||
/// Witness Block
|
||||
WitnessBlock(BlockHash),
|
||||
/// Unknown inventory type
|
||||
Unknown {
|
||||
/// The inventory item type.
|
||||
inv_type: u32,
|
||||
/// The hash of the inventory item
|
||||
hash: [u8; 32],
|
||||
}
|
||||
}
|
||||
|
||||
impl Encodable for Inventory {
|
||||
|
@ -62,6 +69,7 @@ impl Encodable for Inventory {
|
|||
Inventory::WTx(w) => encode_inv!(5, w),
|
||||
Inventory::WitnessTransaction(ref t) => encode_inv!(0x40000001, t),
|
||||
Inventory::WitnessBlock(ref b) => encode_inv!(0x40000002, b),
|
||||
Inventory::Unknown { inv_type: t, hash: ref d } => encode_inv!(t, d),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -77,7 +85,10 @@ impl Decodable for Inventory {
|
|||
5 => Inventory::WTx(Decodable::consensus_decode(&mut d)?),
|
||||
0x40000001 => Inventory::WitnessTransaction(Decodable::consensus_decode(&mut d)?),
|
||||
0x40000002 => Inventory::WitnessBlock(Decodable::consensus_decode(&mut d)?),
|
||||
tp => return Err(encode::Error::UnknownInventoryType(tp)),
|
||||
tp => Inventory::Unknown {
|
||||
inv_type: tp,
|
||||
hash: Decodable::consensus_decode(&mut d)?,
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -84,8 +84,8 @@ impl_consensus_encoding!(VersionMessage, version, services, timestamp,
|
|||
receiver, sender, nonce,
|
||||
user_agent, start_height, relay);
|
||||
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||
/// message rejection reason as a code
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||
pub enum RejectReason {
|
||||
/// malformed message
|
||||
Malformed = 0x01,
|
||||
|
|
|
@ -68,10 +68,6 @@ impl<R: Read> StreamReader<R> {
|
|||
return Err(encode::Error::Io(io::Error::from(io::ErrorKind::UnexpectedEof)));
|
||||
}
|
||||
},
|
||||
Err(encode::Error::UnrecognizedNetworkCommand(message, len)) => {
|
||||
self.unparsed.drain(..len);
|
||||
return Err(encode::Error::UnrecognizedNetworkCommand(message, len))
|
||||
},
|
||||
Err(err) => return Err(err),
|
||||
// We have successfully read from the buffer
|
||||
Ok((message, index)) => {
|
||||
|
|
Loading…
Reference in New Issue