1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
use shared::{Deserializable, DeserializationError, Serializable};

/// A shorthand way of referring to a type of [Message](crate::Message). A `Command` is a single byte, while a [Message](crate::Message) is about 90 bytes.
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Command {
    Version,
    Verack,
    GetBlocks,
    GetData,
    Block,
    GetHeaders,
    Headers,
    Inv,
    MemPool,
    MerkleBlock,
    CmpctBlock,
    GetBlockTxn,
    BlockTxn,
    SendCmpct,
    NotFound,
    Tx,
    Addr,
    Alert,
    FeeFilter,
    FilterAdd,
    FilterClear,
    FilterLoad,
    GetAddr,
    Ping,
    Pong,
    Reject,
    SendHeaders,
}
impl Command {
    pub fn bytes(&self) -> &[u8; 12] {
        match self {
            Command::Version => b"version\0\0\0\0\0",
            Command::Verack => b"verack\0\0\0\0\0\0",
            Command::GetBlocks => b"getblocks\0\0\0",
            Command::GetData => b"getdata\0\0\0\0\0",
            Command::Block => b"block\0\0\0\0\0\0\0",
            Command::GetHeaders => b"getheaders\0\0",
            Command::BlockTxn => b"blocktxn\0\0\0\0",
            Command::CmpctBlock => b"cmpctblock\0\0",
            Command::Headers => b"headers\0\0\0\0\0",
            Command::Inv => b"inv\0\0\0\0\0\0\0\0\0",
            Command::MemPool => b"mempool\0\0\0\0\0",
            Command::MerkleBlock => b"merkleblock\0",
            Command::SendCmpct => b"sendcmpct\0\0\0",
            Command::GetBlockTxn => b"getblocktxn\0",
            Command::NotFound => b"notfound\0\0\0\0",
            Command::Tx => b"tx\0\0\0\0\0\0\0\0\0\0",
            Command::Addr => b"addr\0\0\0\0\0\0\0\0",
            Command::Alert => b"alert\0\0\0\0\0\0\0",
            Command::FeeFilter => b"feefilter\0\0\0",
            Command::FilterAdd => b"filteradd\0\0\0",
            Command::FilterClear => b"filterclear\0",
            Command::FilterLoad => b"filterload\0\0",
            Command::GetAddr => b"getaddr\0\0\0\0\0",
            Command::Ping => b"ping\0\0\0\0\0\0\0\0",
            Command::Pong => b"pong\0\0\0\0\0\0\0\0",
            Command::Reject => b"reject\0\0\0\0\0\0",
            Command::SendHeaders => b"sendheaders\0",
        }
    }
}

impl Serializable for Command {
    fn serialize<W>(&self, target: &mut W) -> Result<(), std::io::Error>
    where
        W: std::io::Write,
    {
        target.write_all(self.bytes())
    }
}

impl Deserializable for Command {
    fn deserialize<T>(reader: &mut T) -> Result<Command, DeserializationError>
    where
        T: std::io::Read,
    {
        let mut buf = [0u8; 12];
        reader.read_exact(&mut buf)?;
        let command = match &buf {
            b"version\0\0\0\0\0" => Command::Version,
            b"verack\0\0\0\0\0\0" => Command::Verack,
            b"getblocks\0\0\0" => Command::GetBlocks,
            b"getdata\0\0\0\0\0" => Command::GetData,
            b"block\0\0\0\0\0\0\0" => Command::Block,
            b"getheaders\0\0" => Command::GetHeaders,
            b"blocktxn\0\0\0\0" => Command::BlockTxn,
            b"cmpctblock\0\0" => Command::CmpctBlock,
            b"headers\0\0\0\0\0" => Command::Headers,
            b"inv\0\0\0\0\0\0\0\0\0" => Command::Inv,
            b"mempool\0\0\0\0\0" => Command::MemPool,
            b"merkleblock\0" => Command::MerkleBlock,
            b"sendcmpct\0\0\0" => Command::SendCmpct,
            b"getblocktxn\0" => Command::GetBlockTxn,
            b"notfound\0\0\0\0" => Command::NotFound,
            b"tx\0\0\0\0\0\0\0\0\0\0" => Command::Tx,
            b"addr\0\0\0\0\0\0\0\0" => Command::Addr,
            b"alert\0\0\0\0\0\0\0" => Command::Alert,
            b"feefilter\0\0\0" => Command::FeeFilter,
            b"filteradd\0\0\0" => Command::FilterAdd,
            b"filterclear\0" => Command::FilterClear,
            b"filterload\0\0" => Command::FilterLoad,
            b"getaddr\0\0\0\0\0" => Command::GetAddr,
            b"ping\0\0\0\0\0\0\0\0" => Command::Ping,
            b"pong\0\0\0\0\0\0\0\0" => Command::Pong,
            b"reject\0\0\0\0\0\0" => Command::Reject,
            b"sendheaders\0" => Command::SendHeaders,
            _ => return Err(DeserializationError::parse(&buf, "Command")),
        };
        Ok(command)
    }
}