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