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