bitcoin/network/
message_network.rs1use std::io;
22use std::borrow::Cow;
23
24use network::address::Address;
25use network::constants::{self, ServiceFlags};
26use consensus::{Encodable, Decodable, ReadExt};
27use consensus::encode;
28use network::message::CommandString;
29use hashes::sha256d;
30
31#[derive(PartialEq, Eq, Clone, Debug)]
35pub struct VersionMessage {
36 pub version: u32,
38 pub services: ServiceFlags,
40 pub timestamp: i64,
42 pub receiver: Address,
44 pub sender: Address,
46 pub nonce: u64,
48 pub user_agent: String,
50 pub start_height: i32,
52 pub relay: bool
56}
57
58impl VersionMessage {
59 pub fn new(
61 services: ServiceFlags,
62 timestamp: i64,
63 receiver: Address,
64 sender: Address,
65 nonce: u64,
66 user_agent: String,
67 start_height: i32,
68 ) -> VersionMessage {
69 VersionMessage {
70 version: constants::PROTOCOL_VERSION,
71 services: services,
72 timestamp: timestamp,
73 receiver: receiver,
74 sender: sender,
75 nonce: nonce,
76 user_agent: user_agent,
77 start_height: start_height,
78 relay: false,
79 }
80 }
81}
82
83impl_consensus_encoding!(VersionMessage, version, services, timestamp,
84 receiver, sender, nonce,
85 user_agent, start_height, relay);
86
87#[derive(PartialEq, Eq, Clone, Copy, Debug)]
89pub enum RejectReason {
90 Malformed = 0x01,
92 Invalid = 0x10,
94 Obsolete = 0x11,
96 Duplicate = 0x12,
98 NonStandard = 0x40,
100 Dust = 0x41,
102 Fee = 0x42,
104 Checkpoint = 0x43
106}
107
108impl Encodable for RejectReason {
109 fn consensus_encode<W: io::Write>(&self, mut e: W) -> Result<usize, io::Error> {
110 e.write_all(&[*self as u8])?;
111 Ok(1)
112 }
113}
114
115impl Decodable for RejectReason {
116 fn consensus_decode<D: io::Read>(mut d: D) -> Result<Self, encode::Error> {
117 Ok(match d.read_u8()? {
118 0x01 => RejectReason::Malformed,
119 0x10 => RejectReason::Invalid,
120 0x11 => RejectReason::Obsolete,
121 0x12 => RejectReason::Duplicate,
122 0x40 => RejectReason::NonStandard,
123 0x41 => RejectReason::Dust,
124 0x42 => RejectReason::Fee,
125 0x43 => RejectReason::Checkpoint,
126 _ => return Err(encode::Error::ParseFailed("unknown reject code"))
127 })
128 }
129}
130
131#[derive(PartialEq, Eq, Clone, Debug)]
133pub struct Reject {
134 pub message: CommandString,
136 pub ccode: RejectReason,
138 pub reason: Cow<'static, str>,
140 pub hash: sha256d::Hash
142}
143
144impl_consensus_encoding!(Reject, message, ccode, reason, hash);
145
146#[cfg(test)]
147mod tests {
148 use super::VersionMessage;
149
150 use hashes::hex::FromHex;
151 use network::constants::ServiceFlags;
152
153 use consensus::encode::{deserialize, serialize};
154
155 #[test]
156 fn version_message_test() {
157 let from_sat = Vec::from_hex("721101000100000000000000e6e0845300000000010000000000000000000000000000000000ffff0000000000000100000000000000fd87d87eeb4364f22cf54dca59412db7208d47d920cffce83ee8102f5361746f7368693a302e392e39392f2c9f040001").unwrap();
159
160 let decode: Result<VersionMessage, _> = deserialize(&from_sat);
161 assert!(decode.is_ok());
162 let real_decode = decode.unwrap();
163 assert_eq!(real_decode.version, 70002);
164 assert_eq!(real_decode.services, ServiceFlags::NETWORK);
165 assert_eq!(real_decode.timestamp, 1401217254);
166 assert_eq!(real_decode.nonce, 16735069437859780935);
168 assert_eq!(real_decode.user_agent, "/Satoshi:0.9.99/".to_string());
169 assert_eq!(real_decode.start_height, 302892);
170 assert_eq!(real_decode.relay, true);
171
172 assert_eq!(serialize(&real_decode), from_sat);
173 }
174}