1use prelude::*;
22
23use io;
24
25use hashes::sha256d;
26
27use network::constants;
28use consensus::encode::{self, Decodable, Encodable};
29use hash_types::{BlockHash, Txid, Wtxid};
30
31#[derive(PartialEq, Eq, Clone, Debug, Copy, Hash, PartialOrd, Ord)]
33pub enum Inventory {
34 Error,
36 Transaction(Txid),
38 Block(BlockHash),
40 WTx(Wtxid),
42 WitnessTransaction(Txid),
44 WitnessBlock(BlockHash),
46 Unknown {
48 inv_type: u32,
50 hash: [u8; 32],
52 }
53}
54
55impl Encodable for Inventory {
56 #[inline]
57 fn consensus_encode<S: io::Write>(&self, mut s: S) -> Result<usize, io::Error> {
58 macro_rules! encode_inv {
59 ($code:expr, $item:expr) => {
60 u32::consensus_encode(&$code, &mut s)? + $item.consensus_encode(&mut s)?
61 }
62 }
63 Ok(match *self {
64 Inventory::Error => encode_inv!(0, sha256d::Hash::default()),
65 Inventory::Transaction(ref t) => encode_inv!(1, t),
66 Inventory::Block(ref b) => encode_inv!(2, b),
67 Inventory::WTx(w) => encode_inv!(5, w),
68 Inventory::WitnessTransaction(ref t) => encode_inv!(0x40000001, t),
69 Inventory::WitnessBlock(ref b) => encode_inv!(0x40000002, b),
70 Inventory::Unknown { inv_type: t, hash: ref d } => encode_inv!(t, d),
71 })
72 }
73}
74
75impl Decodable for Inventory {
76 #[inline]
77 fn consensus_decode<D: io::Read>(mut d: D) -> Result<Self, encode::Error> {
78 let inv_type: u32 = Decodable::consensus_decode(&mut d)?;
79 Ok(match inv_type {
80 0 => Inventory::Error,
81 1 => Inventory::Transaction(Decodable::consensus_decode(&mut d)?),
82 2 => Inventory::Block(Decodable::consensus_decode(&mut d)?),
83 5 => Inventory::WTx(Decodable::consensus_decode(&mut d)?),
84 0x40000001 => Inventory::WitnessTransaction(Decodable::consensus_decode(&mut d)?),
85 0x40000002 => Inventory::WitnessBlock(Decodable::consensus_decode(&mut d)?),
86 tp => Inventory::Unknown {
87 inv_type: tp,
88 hash: Decodable::consensus_decode(&mut d)?,
89 }
90 })
91 }
92}
93
94#[derive(PartialEq, Eq, Clone, Debug)]
98pub struct GetBlocksMessage {
99 pub version: u32,
101 pub locator_hashes: Vec<BlockHash>,
105 pub stop_hash: BlockHash,
107}
108
109#[derive(PartialEq, Eq, Clone, Debug)]
111pub struct GetHeadersMessage {
112 pub version: u32,
114 pub locator_hashes: Vec<BlockHash>,
118 pub stop_hash: BlockHash
120}
121
122impl GetBlocksMessage {
123 pub fn new(locator_hashes: Vec<BlockHash>, stop_hash: BlockHash) -> GetBlocksMessage {
125 GetBlocksMessage {
126 version: constants::PROTOCOL_VERSION,
127 locator_hashes,
128 stop_hash,
129 }
130 }
131}
132
133impl_consensus_encoding!(GetBlocksMessage, version, locator_hashes, stop_hash);
134
135impl GetHeadersMessage {
136 pub fn new(locator_hashes: Vec<BlockHash>, stop_hash: BlockHash) -> GetHeadersMessage {
138 GetHeadersMessage {
139 version: constants::PROTOCOL_VERSION,
140 locator_hashes,
141 stop_hash,
142 }
143 }
144}
145
146impl_consensus_encoding!(GetHeadersMessage, version, locator_hashes, stop_hash);
147
148#[cfg(test)]
149mod tests {
150 use super::{Vec, GetHeadersMessage, GetBlocksMessage};
151
152 use hashes::hex::FromHex;
153
154 use consensus::encode::{deserialize, serialize};
155 use core::default::Default;
156
157 #[test]
158 fn getblocks_message_test() {
159 let from_sat = Vec::from_hex("72110100014a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b0000000000000000000000000000000000000000000000000000000000000000").unwrap();
160 let genhash = Vec::from_hex("4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b").unwrap();
161
162 let decode: Result<GetBlocksMessage, _> = deserialize(&from_sat);
163 assert!(decode.is_ok());
164 let real_decode = decode.unwrap();
165 assert_eq!(real_decode.version, 70002);
166 assert_eq!(real_decode.locator_hashes.len(), 1);
167 assert_eq!(serialize(&real_decode.locator_hashes[0]), genhash);
168 assert_eq!(real_decode.stop_hash, Default::default());
169
170 assert_eq!(serialize(&real_decode), from_sat);
171 }
172
173 #[test]
174 fn getheaders_message_test() {
175 let from_sat = Vec::from_hex("72110100014a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b0000000000000000000000000000000000000000000000000000000000000000").unwrap();
176 let genhash = Vec::from_hex("4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b").unwrap();
177
178 let decode: Result<GetHeadersMessage, _> = deserialize(&from_sat);
179 assert!(decode.is_ok());
180 let real_decode = decode.unwrap();
181 assert_eq!(real_decode.version, 70002);
182 assert_eq!(real_decode.locator_hashes.len(), 1);
183 assert_eq!(serialize(&real_decode.locator_hashes[0]), genhash);
184 assert_eq!(real_decode.stop_hash, Default::default());
185
186 assert_eq!(serialize(&real_decode), from_sat);
187 }
188}
189