1use linked_hash_map::LinkedHashMap;
2use messages::{BlockHeader, OutPoint, Payload, Tx, TxOut};
3use std::collections::{HashSet, VecDeque};
4use std::fmt;
5use std::io;
6use std::io::{Read, Write};
7use util::{sha256d, var_int, Error, Hash256, Result, Serializable};
8
9pub const BITCOIN_CASH_FORK_HEIGHT: i32 = 478558;
11
12#[derive(Default, PartialEq, Eq, Hash, Clone)]
14pub struct Block {
15 pub header: BlockHeader,
17 pub txns: Vec<Tx>,
19}
20
21impl Block {
22 pub fn inputs(&self) -> Result<HashSet<OutPoint>> {
24 let mut inputs = HashSet::new();
25 for txn in self.txns.iter() {
26 if !txn.coinbase() {
27 for input in txn.inputs.iter() {
28 if inputs.contains(&input.prev_output) {
29 let msg = "Input double spent".to_string();
30 return Err(Error::BadData(msg));
31 }
32 inputs.insert(input.prev_output.clone());
33 }
34 }
35 }
36 Ok(inputs)
37 }
38
39 pub fn outputs(&self) -> Result<LinkedHashMap<OutPoint, TxOut>> {
41 let mut outputs = LinkedHashMap::new();
42 for txn in self.txns.iter() {
43 let hash = txn.hash();
44 for index in 0..txn.outputs.len() as u32 {
45 outputs.insert(
46 OutPoint { hash, index },
47 txn.outputs[index as usize].clone(),
48 );
49 }
50 }
51 Ok(outputs)
52 }
53
54 pub fn validate(&self, height: i32, utxos: &LinkedHashMap<OutPoint, TxOut>) -> Result<()> {
56 if self.txns.len() == 0 {
57 return Err(Error::BadData("Txn count is zero".to_string()));
58 }
59
60 if self.merkle_root() != self.header.merkle_root {
61 return Err(Error::BadData("Bad merkle root".to_string()));
62 }
63
64 let mut has_coinbase = false;
65 let require_sighash_forkid = height >= BITCOIN_CASH_FORK_HEIGHT;
66 for txn in self.txns.iter() {
67 if !txn.coinbase() {
68 txn.validate(require_sighash_forkid, utxos)?;
69 } else if has_coinbase {
70 return Err(Error::BadData("Multiple coinbases".to_string()));
71 } else {
72 has_coinbase = true;
73 }
74 }
75 if !has_coinbase {
76 return Err(Error::BadData("No coinbase".to_string()));
77 }
78
79 Ok(())
80 }
81
82 fn merkle_root(&self) -> Hash256 {
84 let mut row = VecDeque::new();
85 for tx in self.txns.iter() {
86 row.push_back(tx.hash());
87 }
88 while row.len() > 1 {
89 let mut n = row.len();
90 while n > 0 {
91 n -= 1;
92 let h1 = row.pop_front().unwrap();
93 let h2 = if n == 0 {
94 h1.clone()
95 } else {
96 n -= 1;
97 row.pop_front().unwrap()
98 };
99 let mut h = Vec::with_capacity(64);
100 h1.write(&mut h).unwrap();
101 h2.write(&mut h).unwrap();
102 row.push_back(sha256d(&h));
103 }
104 }
105 return row.pop_front().unwrap();
106 }
107}
108
109impl Serializable<Block> for Block {
110 fn read(reader: &mut dyn Read) -> Result<Block> {
111 let header = BlockHeader::read(reader)?;
112 let txn_count = var_int::read(reader)?;
113 let mut txns = Vec::with_capacity(txn_count as usize);
114 for _i in 0..txn_count {
115 txns.push(Tx::read(reader)?);
116 }
117 Ok(Block { header, txns })
118 }
119
120 fn write(&self, writer: &mut dyn Write) -> io::Result<()> {
121 self.header.write(writer)?;
122 var_int::write(self.txns.len() as u64, writer)?;
123 for txn in self.txns.iter() {
124 txn.write(writer)?;
125 }
126 Ok(())
127 }
128}
129
130impl Payload<Block> for Block {
131 fn size(&self) -> usize {
132 let mut size = BlockHeader::SIZE;
133 size += var_int::size(self.txns.len() as u64);
134 for txn in self.txns.iter() {
135 size += txn.size();
136 }
137 size
138 }
139}
140
141impl fmt::Debug for Block {
142 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
143 if self.txns.len() <= 3 {
144 f.debug_struct("Block")
145 .field("header", &self.header)
146 .field("txns", &self.txns)
147 .finish()
148 } else {
149 let txns = format!("[<{} transactions>]", self.txns.len());
150 f.debug_struct("Block")
151 .field("header", &self.header)
152 .field("txns", &txns)
153 .finish()
154 }
155 }
156}
157
158#[cfg(test)]
159mod tests {
160 use super::*;
161 use hex;
162 use messages::{OutPoint, TxIn, TxOut};
163 use script::Script;
164 use std::io::Cursor;
165 use util::{Amount, Hash256};
166
167 #[test]
168 fn read_bytes() {
169 let b = hex::decode("010000004860eb18bf1b1620e37e9490fc8a427514416fd75159ab86688e9a8300000000d5fdcc541e25de1c7a5addedf24858b8bb665c9f36ef744ee42c316022c90f9bb0bc6649ffff001d08d2bd610101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0704ffff001d010bffffffff0100f2052a010000004341047211a824f55b505228e4c3d5194c1fcfaa15a456abdf37f9b9d97a4040afc073dee6c89064984f03385237d92167c13e236446b417ab79a0fcae412ae3316b77ac00000000").unwrap();
170 let block = Block::read(&mut Cursor::new(&b)).unwrap();
171 assert!(
172 block == Block {
173 header: BlockHeader {
174 version: 1,
175 prev_hash: Hash256::decode(
176 "00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048",
177 ).unwrap(),
178 merkle_root: Hash256::decode(
179 "9b0fc92260312ce44e74ef369f5c66bbb85848f2eddd5a7a1cde251e54ccfdd5",
180 ).unwrap(),
181 timestamp: 1231469744,
182 bits: 486604799,
183 nonce: 1639830024,
184 },
185 txns: vec![Tx {
186 version: 1,
187 inputs: vec![TxIn {
188 prev_output: OutPoint {
189 hash: Hash256([0; 32]),
190 index: 4294967295,
191 },
192 sig_script: Script(vec![4, 255, 255, 0, 29, 1, 11]),
193 sequence: 4294967295,
194 }],
195 outputs: vec![TxOut {
196 amount: Amount(5000000000),
197 pk_script: Script(vec![
198 65, 4, 114, 17, 168, 36, 245, 91, 80, 82, 40, 228, 195, 213, 25, 76,
199 31, 207, 170, 21, 164, 86, 171, 223, 55, 249, 185, 217, 122, 64, 64,
200 175, 192, 115, 222, 230, 200, 144, 100, 152, 79, 3, 56, 82, 55, 217,
201 33, 103, 193, 62, 35, 100, 70, 180, 23, 171, 121, 160, 252, 174, 65,
202 42, 227, 49, 107, 119, 172,
203 ]),
204 }],
205 lock_time: 0,
206 }],
207 }
208 );
209 }
210
211 #[test]
212 fn write_read() {
213 let mut v = Vec::new();
214 let block = Block {
215 header: BlockHeader {
216 version: 77,
217 prev_hash: Hash256::decode(
218 "abcdabcdabcdabcd1234123412341234abcdabcdabcdabcd1234123412341234",
219 ).unwrap(),
220 merkle_root: Hash256::decode(
221 "1234567809876543123456780987654312345678098765431234567809876543",
222 ).unwrap(),
223 timestamp: 7,
224 bits: 8,
225 nonce: 9,
226 },
227 txns: vec![Tx {
228 version: 7,
229 inputs: vec![TxIn {
230 prev_output: OutPoint {
231 hash: Hash256([7; 32]),
232 index: 3,
233 },
234 sig_script: Script(vec![9, 8, 7]),
235 sequence: 42,
236 }],
237 outputs: vec![TxOut {
238 amount: Amount(23),
239 pk_script: Script(vec![1, 2, 3, 4, 5]),
240 }],
241 lock_time: 4,
242 }],
243 };
244 block.write(&mut v).unwrap();
245 assert!(v.len() == block.size());
246 assert!(Block::read(&mut Cursor::new(&v)).unwrap() == block);
247 }
248}