1use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
2use messages::message::Payload;
3use messages::node_addr::NodeAddr;
4use std::io;
5use std::io::{Read, Write};
6use std::time::UNIX_EPOCH;
7use util::{secs_since, var_int, Error, Result, Serializable};
8
9pub const PROTOCOL_VERSION: u32 = 70015;
11
12pub const MIN_SUPPORTED_PROTOCOL_VERSION: u32 = 70001;
14
15pub const UNKNOWN_IP: [u8; 16] = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 127, 0, 0, 1];
17
18pub const NODE_NONE: u64 = 0;
20
21pub const NODE_NETWORK: u64 = 1;
23
24pub const NODE_BITCOIN_CASH: u64 = 1 << 5;
26
27#[derive(Debug, Default, PartialEq, Eq, Hash, Clone)]
29pub struct Version {
30 pub version: u32,
32 pub services: u64,
34 pub timestamp: i64,
36 pub recv_addr: NodeAddr,
38 pub tx_addr: NodeAddr,
40 pub nonce: u64,
42 pub user_agent: String,
44 pub start_height: i32,
46 pub relay: bool,
48}
49
50impl Version {
51 pub fn validate(&self) -> Result<()> {
53 if self.version < MIN_SUPPORTED_PROTOCOL_VERSION {
54 let msg = format!("Unsupported protocol version: {}", self.version);
55 return Err(Error::BadData(msg));
56 }
57 let now = secs_since(UNIX_EPOCH) as i64;
58 if (self.timestamp - now).abs() > 2 * 60 * 60 {
59 let msg = format!("Timestamp too old: {}", self.timestamp);
60 return Err(Error::BadData(msg));
61 }
62 Ok(())
63 }
64}
65
66impl Serializable<Version> for Version {
67 fn read(reader: &mut dyn Read) -> Result<Version> {
68 let mut ret = Version {
69 ..Default::default()
70 };
71 ret.version = reader.read_u32::<LittleEndian>()?;
72 ret.services = reader.read_u64::<LittleEndian>()?;
73 ret.timestamp = reader.read_i64::<LittleEndian>()?;
74 ret.recv_addr = NodeAddr::read(reader)?;
75 ret.tx_addr = NodeAddr::read(reader)?;
76 ret.nonce = reader.read_u64::<LittleEndian>()?;
77 let user_agent_size = var_int::read(reader)? as usize;
78 let mut user_agent_bytes = vec![0; user_agent_size];
79 reader.read(&mut user_agent_bytes)?;
80 ret.user_agent = String::from_utf8(user_agent_bytes)?;
81 ret.start_height = reader.read_i32::<LittleEndian>()?;
82 ret.relay = reader.read_u8()? == 0x01;
83 Ok(ret)
84 }
85
86 fn write(&self, writer: &mut dyn Write) -> io::Result<()> {
87 writer.write_u32::<LittleEndian>(self.version)?;
88 writer.write_u64::<LittleEndian>(self.services)?;
89 writer.write_i64::<LittleEndian>(self.timestamp)?;
90 self.recv_addr.write(writer)?;
91 self.tx_addr.write(writer)?;
92 writer.write_u64::<LittleEndian>(self.nonce)?;
93 var_int::write(self.user_agent.as_bytes().len() as u64, writer)?;
94 writer.write(&self.user_agent.as_bytes())?;
95 writer.write_i32::<LittleEndian>(self.start_height)?;
96 writer.write_u8(if self.relay { 0x01 } else { 0x00 })?;
97 Ok(())
98 }
99}
100
101impl Payload<Version> for Version {
102 fn size(&self) -> usize {
103 33 + self.recv_addr.size()
104 + self.tx_addr.size()
105 + var_int::size(self.user_agent.as_bytes().len() as u64)
106 + self.user_agent.as_bytes().len()
107 }
108}
109
110#[cfg(test)]
111mod tests {
112 use super::*;
113 use hex;
114 use std::io::Cursor;
115
116 #[test]
117 fn read_bytes() {
118 let b = hex::decode("7f1101002500000000000000f2d2d25a00000000000000000000000000000000000000000000ffff2d32bffbdd1725000000000000000000000000000000000000000000000000008d501d3bb5369deb242f426974636f696e204142433a302e31362e30284542382e303b20626974636f7265292f6606080001".as_bytes()).unwrap();
119 let v = Version::read(&mut Cursor::new(&b)).unwrap();
120 assert!(v.version == 70015);
121 assert!(v.services == 37);
122 assert!(v.timestamp == 1523766002);
123 assert!(v.recv_addr.services == 0);
124 assert!(
125 v.recv_addr.ip.octets() == [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 45, 50, 191, 251]
126 );
127 assert!(v.recv_addr.port == 56599);
128 assert!(v.tx_addr.services == 37);
129 assert!(v.tx_addr.ip.octets() == [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
130 assert!(v.tx_addr.port == 0);
131 assert!(v.nonce == 16977786322265395341);
132 assert!(v.user_agent == "/Bitcoin ABC:0.16.0(EB8.0; bitcore)/");
133 assert!(v.start_height == 525926);
134 assert!(v.relay == true);
135 }
136
137 #[test]
138 fn write_read() {
139 let mut v = Vec::new();
140 let m = Version {
141 version: MIN_SUPPORTED_PROTOCOL_VERSION,
142 services: 77,
143 timestamp: 1234,
144 recv_addr: NodeAddr {
145 ..Default::default()
146 },
147 tx_addr: NodeAddr {
148 ..Default::default()
149 },
150 nonce: 99,
151 user_agent: "dummy".to_string(),
152 start_height: 22,
153 relay: true,
154 };
155 m.write(&mut v).unwrap();
156 assert!(v.len() == m.size());
157 assert!(Version::read(&mut Cursor::new(&v)).unwrap() == m);
158 }
159
160 #[test]
161 fn validate() {
162 let m = Version {
163 version: MIN_SUPPORTED_PROTOCOL_VERSION,
164 services: 77,
165 timestamp: secs_since(UNIX_EPOCH) as i64,
166 recv_addr: NodeAddr {
167 ..Default::default()
168 },
169 tx_addr: NodeAddr {
170 ..Default::default()
171 },
172 nonce: 99,
173 user_agent: "dummy".to_string(),
174 start_height: 22,
175 relay: true,
176 };
177 assert!(m.validate().is_ok());
179 let m2 = Version {
181 version: 0,
182 ..m.clone()
183 };
184 assert!(m2.validate().is_err());
185 let m3 = Version {
187 timestamp: 0,
188 ..m.clone()
189 };
190 assert!(m3.validate().is_err());
191 }
192}