cs_mwc_bch/messages/
reject.rs1use byteorder::{ReadBytesExt, WriteBytesExt};
2use messages::message::Payload;
3use std::fmt;
4use std::io;
5use std::io::{Cursor, Read, Write};
6use util::{var_int, Error, Hash256, Result, Serializable};
7
8pub const REJECT_MALFORMED: u8 = 0x01;
10pub const REJECT_INVALID: u8 = 0x10;
11pub const REJECT_OBSOLETE: u8 = 0x11;
12pub const REJECT_DUPLICATE: u8 = 0x12;
13pub const REJECT_NONSTANDARD: u8 = 0x40;
14pub const REJECT_DUST: u8 = 0x41;
15pub const REJECT_INSUFFICIENT_FEE: u8 = 0x42;
16pub const REJECT_CHECKPOINT: u8 = 0x43;
17
18#[derive(Default, PartialEq, Eq, Hash, Clone)]
20pub struct Reject {
21 pub message: String,
23 pub code: u8,
25 pub reason: String,
27 pub data: Vec<u8>,
31}
32
33impl Reject {
34 pub fn txid(&self) -> Result<Hash256> {
36 if self.data.len() != 32 {
37 return Err(Error::InvalidOperation("No transaction hash".to_string()));
38 }
39 let mut txid = Hash256([0; 32]);
40 txid.0.clone_from_slice(&self.data);
41 Ok(txid)
42 }
43}
44
45impl Serializable<Reject> for Reject {
46 fn read(reader: &mut dyn Read) -> Result<Reject> {
47 let message_size = var_int::read(reader)? as usize;
48 let mut message_bytes = vec![0; message_size];
49 reader.read(&mut message_bytes)?;
50 let message = String::from_utf8(message_bytes)?;
51 let code = reader.read_u8()?;
52 let reason_size = var_int::read(reader)? as usize;
53 let mut reason_bytes = vec![0; reason_size];
54 reader.read(&mut reason_bytes)?;
55 let reason = String::from_utf8(reason_bytes)?;
56 let mut data = vec![];
57 if message == "block".to_string() || message == "tx".to_string() {
58 data = vec![0_u8; 32];
59 reader.read(&mut data)?;
60 }
61 Ok(Reject {
62 message,
63 code,
64 reason,
65 data,
66 })
67 }
68
69 fn write(&self, writer: &mut dyn Write) -> io::Result<()> {
70 var_int::write(self.message.as_bytes().len() as u64, writer)?;
71 writer.write(&self.message.as_bytes())?;
72 writer.write_u8(self.code)?;
73 var_int::write(self.reason.as_bytes().len() as u64, writer)?;
74 writer.write(&self.reason.as_bytes())?;
75 writer.write(&self.data)?;
76 Ok(())
77 }
78}
79
80impl Payload<Reject> for Reject {
81 fn size(&self) -> usize {
82 var_int::size(self.message.as_bytes().len() as u64)
83 + self.message.as_bytes().len()
84 + 1
85 + var_int::size(self.reason.as_bytes().len() as u64)
86 + self.reason.as_bytes().len()
87 + self.data.len()
88 }
89}
90
91impl fmt::Debug for Reject {
92 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
93 let mut data_str = "".to_string();
94 if self.message == "block".to_string() || self.message == "tx".to_string() {
95 let mut data = Cursor::new(&self.data);
96 data_str = Hash256::read(&mut data).unwrap().encode();
97 }
98 f.debug_struct("Reject")
99 .field("message", &self.message)
100 .field("code", &self.code)
101 .field("reason", &self.reason)
102 .field("data", &data_str)
103 .finish()
104 }
105}
106
107#[cfg(test)]
108mod tests {
109 use super::*;
110 use hex;
111 use std::io::Cursor;
112
113 #[test]
114 fn txid() {
115 let mut reject = Reject {
116 data: vec![5; 32],
117 ..Default::default()
118 };
119 assert!(reject.txid().is_ok());
120 reject.data = vec![3; 33];
121 assert!(reject.txid().is_err());
122 }
123
124 #[test]
125 fn read_bytes() {
126 let b = hex::decode("027478104f6d616e6461746f72792d7363726970742d7665726966792d666c61672d6661696c65642028536372697074206661696c656420616e204f505f455155414c564552494659206f7065726174696f6e292f174bfe9e5b6e32ef2fabd164df5469f44977d93e0625238465ded771083993".as_bytes()).unwrap();
127 let m = Reject::read(&mut Cursor::new(&b)).unwrap();
128 assert!(m.message == "tx".to_string());
129 assert!(m.code == REJECT_INVALID);
130 assert!(m.reason == "mandatory-script-verify-flag-failed (Script failed an OP_EQUALVERIFY operation)".to_string());
131 let data = "2f174bfe9e5b6e32ef2fabd164df5469f44977d93e0625238465ded771083993";
132 assert!(m.data == hex::decode(data).unwrap());
133 }
134
135 #[test]
136 fn write_read() {
137 let mut v = Vec::new();
138 let p = Reject {
139 message: "block".to_string(),
140 code: REJECT_INVALID,
141 reason: "Block too small".to_string(),
142 data: vec![5; 32],
143 };
144 p.write(&mut v).unwrap();
145 assert!(v.len() == p.size());
146 assert!(Reject::read(&mut Cursor::new(&v)).unwrap() == p);
147 }
148}