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
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use messages::message::Payload;
use messages::version::MIN_SUPPORTED_PROTOCOL_VERSION;
use std::io;
use std::io::{Read, Write};
use util::{var_int, Error, Hash256, Result, Serializable};
pub const NO_HASH_STOP: Hash256 = Hash256([0; 32]);
#[derive(Debug, Default, PartialEq, Eq, Hash, Clone)]
pub struct BlockLocator {
pub version: u32,
pub block_locator_hashes: Vec<Hash256>,
pub hash_stop: Hash256,
}
impl BlockLocator {
pub fn validate(&self) -> Result<()> {
if self.version < MIN_SUPPORTED_PROTOCOL_VERSION as u32 {
let msg = format!("Unsupported protocol version: {}", self.version);
return Err(Error::BadData(msg));
}
Ok(())
}
}
impl Serializable<BlockLocator> for BlockLocator {
fn read(reader: &mut dyn Read) -> Result<BlockLocator> {
let version = reader.read_u32::<LittleEndian>()?;
let num_hashes = var_int::read(reader)?;
let mut block_locator_hashes = Vec::new();
for _i in 0..num_hashes {
block_locator_hashes.push(Hash256::read(reader)?);
}
let hash_stop = Hash256::read(reader)?;
Ok(BlockLocator {
version,
block_locator_hashes,
hash_stop,
})
}
fn write(&self, writer: &mut dyn Write) -> io::Result<()> {
writer.write_u32::<LittleEndian>(self.version)?;
var_int::write(self.block_locator_hashes.len() as u64, writer)?;
for hash in self.block_locator_hashes.iter() {
hash.write(writer)?;
}
self.hash_stop.write(writer)?;
Ok(())
}
}
impl Payload<BlockLocator> for BlockLocator {
fn size(&self) -> usize {
4 + var_int::size(self.block_locator_hashes.len() as u64)
+ self.block_locator_hashes.len() * 32
+ 32
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::io::Cursor;
#[test]
fn write_read() {
let mut v = Vec::new();
let p = BlockLocator {
version: 12345,
block_locator_hashes: vec![
NO_HASH_STOP,
Hash256::decode("6677889900667788990066778899006677889900667788990066778899006677")
.unwrap(),
],
hash_stop: Hash256::decode(
"1122334455112233445511223344551122334455112233445511223344551122",
).unwrap(),
};
p.write(&mut v).unwrap();
assert!(v.len() == p.size());
assert!(BlockLocator::read(&mut Cursor::new(&v)).unwrap() == p);
}
}