cs_mwc_bch/messages/
block.rs

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
9/// Block height that Bitcoin Cash forked from BTC
10pub const BITCOIN_CASH_FORK_HEIGHT: i32 = 478558;
11
12/// Block of transactions
13#[derive(Default, PartialEq, Eq, Hash, Clone)]
14pub struct Block {
15    /// Block header
16    pub header: BlockHeader,
17    /// Block transactions
18    pub txns: Vec<Tx>,
19}
20
21impl Block {
22    /// Returns a set of the inputs spent in this block
23    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    /// Returns a map of the new outputs generated from this block including those spent within the block
40    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    /// Checks that the block is valid
55    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    /// Calculates the merkle root from the transactions
83    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}