1use prelude::*;
56
57use io;
58
59use hashes::Hash;
60use hash_types::{Txid, TxMerkleNode};
61
62use blockdata::transaction::Transaction;
63use blockdata::constants::{MAX_BLOCK_WEIGHT, MIN_TRANSACTION_WEIGHT};
64use consensus::encode::{self, Decodable, Encodable};
65use util::merkleblock::MerkleBlockError::*;
66use {Block, BlockHeader};
67
68#[derive(Clone, PartialEq, Eq, Debug)]
70pub enum MerkleBlockError {
71 MerkleRootMismatch,
73 NoTransactions,
75 TooManyTransactions,
77 BadFormat(String),
79}
80
81#[derive(PartialEq, Eq, Clone, Debug)]
115pub struct PartialMerkleTree {
116 num_transactions: u32,
118 bits: Vec<bool>,
120 hashes: Vec<TxMerkleNode>,
122}
123
124impl PartialMerkleTree {
125 pub fn from_txids(txids: &[Txid], matches: &[bool]) -> Self {
153 assert_ne!(txids.len(), 0);
155 assert_eq!(txids.len(), matches.len());
156
157 let mut pmt = PartialMerkleTree {
158 num_transactions: txids.len() as u32,
159 bits: Vec::with_capacity(txids.len()),
160 hashes: vec![],
161 };
162 let mut height = 0;
164 while pmt.calc_tree_width(height) > 1 {
165 height += 1;
166 }
167 pmt.traverse_and_build(height, 0, txids, matches);
169 pmt
170 }
171
172 pub fn extract_matches(
176 &self,
177 matches: &mut Vec<Txid>,
178 indexes: &mut Vec<u32>,
179 ) -> Result<TxMerkleNode, MerkleBlockError> {
180 matches.clear();
181 indexes.clear();
182 if self.num_transactions == 0 {
184 return Err(NoTransactions);
185 };
186 if self.num_transactions > MAX_BLOCK_WEIGHT / MIN_TRANSACTION_WEIGHT {
188 return Err(TooManyTransactions);
189 }
190 if self.hashes.len() as u32 > self.num_transactions {
192 return Err(BadFormat("Proof contains more hashes than transactions".to_owned()));
193 };
194 if self.bits.len() < self.hashes.len() {
196 return Err(BadFormat("Proof contains less bits than hashes".to_owned()));
197 };
198 let mut height = 0;
200 while self.calc_tree_width(height) > 1 {
201 height += 1;
202 }
203 let mut bits_used = 0u32;
205 let mut hash_used = 0u32;
206 let hash_merkle_root =
207 self.traverse_and_extract(height, 0, &mut bits_used, &mut hash_used, matches, indexes)?;
208 if (bits_used + 7) / 8 != (self.bits.len() as u32 + 7) / 8 {
211 return Err(BadFormat("Not all bit were consumed".to_owned()));
212 }
213 if hash_used != self.hashes.len() as u32 {
215 return Err(BadFormat("Not all hashes were consumed".to_owned()));
216 }
217 Ok(TxMerkleNode::from_inner(hash_merkle_root.into_inner()))
218 }
219
220 #[inline]
223 fn calc_tree_width(&self, height: u32) -> u32 {
224 (self.num_transactions + (1 << height) - 1) >> height
225 }
226
227 fn calc_hash(&self, height: u32, pos: u32, txids: &[Txid]) -> TxMerkleNode {
229 if height == 0 {
230 TxMerkleNode::from_inner(txids[pos as usize].into_inner())
232 } else {
233 let left = self.calc_hash(height - 1, pos * 2, txids);
235 let right = if pos * 2 + 1 < self.calc_tree_width(height - 1) {
237 self.calc_hash(height - 1, pos * 2 + 1, txids)
238 } else {
239 left
240 };
241 PartialMerkleTree::parent_hash(left, right)
243 }
244 }
245
246 fn traverse_and_build(&mut self, height: u32, pos: u32, txids: &[Txid], matches: &[bool]) {
248 let mut parent_of_match = false;
250 let mut p = pos << height;
251 while p < (pos + 1) << height && p < self.num_transactions {
252 parent_of_match |= matches[p as usize];
253 p += 1;
254 }
255 self.bits.push(parent_of_match);
257
258 if height == 0 || !parent_of_match {
259 let hash = self.calc_hash(height, pos, txids);
261 self.hashes.push(hash);
262 } else {
263 self.traverse_and_build(height - 1, pos * 2, txids, matches);
265 if pos * 2 + 1 < self.calc_tree_width(height - 1) {
266 self.traverse_and_build(height - 1, pos * 2 + 1, txids, matches);
267 }
268 }
269 }
270
271 fn traverse_and_extract(
274 &self,
275 height: u32,
276 pos: u32,
277 bits_used: &mut u32,
278 hash_used: &mut u32,
279 matches: &mut Vec<Txid>,
280 indexes: &mut Vec<u32>,
281 ) -> Result<TxMerkleNode, MerkleBlockError> {
282 if *bits_used as usize >= self.bits.len() {
283 return Err(BadFormat("Overflowed the bits array".to_owned()));
284 }
285 let parent_of_match = self.bits[*bits_used as usize];
286 *bits_used += 1;
287 if height == 0 || !parent_of_match {
288 if *hash_used as usize >= self.hashes.len() {
290 return Err(BadFormat("Overflowed the hash array".to_owned()));
291 }
292 let hash = self.hashes[*hash_used as usize];
293 *hash_used += 1;
294 if height == 0 && parent_of_match {
295 matches.push(Txid::from_inner(hash.into_inner()));
297 indexes.push(pos);
298 }
299 Ok(hash)
300 } else {
301 let left = self.traverse_and_extract(
303 height - 1,
304 pos * 2,
305 bits_used,
306 hash_used,
307 matches,
308 indexes,
309 )?;
310 let right;
311 if pos * 2 + 1 < self.calc_tree_width(height - 1) {
312 right = self.traverse_and_extract(
313 height - 1,
314 pos * 2 + 1,
315 bits_used,
316 hash_used,
317 matches,
318 indexes,
319 )?;
320 if right == left {
321 return Err(BadFormat("Found identical transaction hashes".to_owned()));
324 }
325 } else {
326 right = left;
327 }
328 Ok(PartialMerkleTree::parent_hash(left, right))
330 }
331 }
332
333 fn parent_hash(left: TxMerkleNode, right: TxMerkleNode) -> TxMerkleNode {
335 let mut encoder = TxMerkleNode::engine();
336 left.consensus_encode(&mut encoder).expect("engines don't error");
337 right.consensus_encode(&mut encoder).expect("engines don't error");
338 TxMerkleNode::from_engine(encoder)
339 }
340}
341
342impl Encodable for PartialMerkleTree {
343 fn consensus_encode<S: io::Write>(&self, mut s: S) -> Result<usize, io::Error> {
344 let ret = self.num_transactions.consensus_encode(&mut s)?
345 + self.hashes.consensus_encode(&mut s)?;
346 let mut bytes: Vec<u8> = vec![0; (self.bits.len() + 7) / 8];
347 for p in 0..self.bits.len() {
348 bytes[p / 8] |= (self.bits[p] as u8) << (p % 8) as u8;
349 }
350 Ok(ret + bytes.consensus_encode(s)?)
351 }
352}
353
354impl Decodable for PartialMerkleTree {
355 fn consensus_decode<D: io::Read>(mut d: D) -> Result<Self, encode::Error> {
356 let num_transactions: u32 = Decodable::consensus_decode(&mut d)?;
357 let hashes: Vec<TxMerkleNode> = Decodable::consensus_decode(&mut d)?;
358
359 let bytes: Vec<u8> = Decodable::consensus_decode(d)?;
360 let mut bits: Vec<bool> = vec![false; bytes.len() * 8];
361
362 for (p, bit) in bits.iter_mut().enumerate() {
363 *bit = (bytes[p / 8] & (1 << (p % 8) as u8)) != 0;
364 }
365 Ok(PartialMerkleTree {
366 num_transactions,
367 hashes,
368 bits,
369 })
370 }
371}
372
373#[derive(PartialEq, Eq, Clone, Debug)]
378pub struct MerkleBlock {
379 pub header: BlockHeader,
381 pub txn: PartialMerkleTree,
383}
384
385impl MerkleBlock {
386 pub fn from_block_with_predicate<F>(block: &Block, match_txids: F) -> Self
424 where
425 F: Fn(&Txid) -> bool
426 {
427 let block_txids: Vec<_> = block.txdata.iter().map(Transaction::txid).collect();
428 Self::from_header_txids_with_predicate(&block.header, &block_txids, match_txids)
429 }
430
431 #[cfg(feature = "std")]
433 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
434 #[deprecated(since = "0.26.2", note = "use from_block_with_predicate")]
435 pub fn from_block(block: &Block, match_txids: &::std::collections::HashSet<Txid>) -> Self {
436 Self::from_block_with_predicate(block, |t| match_txids.contains(t))
437 }
438
439 pub fn from_header_txids_with_predicate<F>(
444 header: &BlockHeader,
445 block_txids: &[Txid],
446 match_txids: F,
447 ) -> Self
448 where
449 F: Fn(&Txid) -> bool
450 {
451 let matches: Vec<bool> = block_txids
452 .iter()
453 .map(match_txids)
454 .collect();
455
456 let pmt = PartialMerkleTree::from_txids(block_txids, &matches);
457 MerkleBlock {
458 header: *header,
459 txn: pmt,
460 }
461 }
462
463 #[cfg(feature = "std")]
465 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
466 #[deprecated(since = "0.26.2", note = "use from_header_txids_with_predicate")]
467 pub fn from_header_txids(
468 header: &BlockHeader,
469 block_txids: &[Txid],
470 match_txids: &::std::collections::HashSet<Txid>,
471 ) -> Self {
472 Self::from_header_txids_with_predicate(header, block_txids, |t| match_txids.contains(t))
473 }
474
475 pub fn extract_matches(
479 &self,
480 matches: &mut Vec<Txid>,
481 indexes: &mut Vec<u32>,
482 ) -> Result<(), MerkleBlockError> {
483 let merkle_root = self.txn.extract_matches(matches, indexes)?;
484
485 if merkle_root.eq(&self.header.merkle_root) {
486 Ok(())
487 } else {
488 Err(MerkleRootMismatch)
489 }
490 }
491}
492
493impl Encodable for MerkleBlock {
494 fn consensus_encode<S: io::Write>(&self, mut s: S) -> Result<usize, io::Error> {
495 let len = self.header.consensus_encode(&mut s)?
496 + self.txn.consensus_encode(s)?;
497 Ok(len)
498 }
499}
500
501impl Decodable for MerkleBlock {
502 fn consensus_decode<D: io::Read>(mut d: D) -> Result<Self, encode::Error> {
503 Ok(MerkleBlock {
504 header: Decodable::consensus_decode(&mut d)?,
505 txn: Decodable::consensus_decode(d)?,
506 })
507 }
508}
509
510#[cfg(test)]
511mod tests {
512 use core::cmp::min;
513
514 use hashes::Hash;
515 use hashes::hex::{FromHex, ToHex};
516 use hash_types::{Txid, TxMerkleNode};
517 use secp256k1::rand::prelude::*;
518
519 use consensus::encode::{deserialize, serialize};
520 use util::hash::bitcoin_merkle_root;
521 use util::merkleblock::{MerkleBlock, PartialMerkleTree};
522 use Block;
523
524 #[test]
525 fn pmt_tests() {
526 let mut rng = thread_rng();
527 let tx_counts = vec![1, 4, 7, 17, 56, 100, 127, 256, 312, 513, 1000, 4095];
528
529 for num_tx in tx_counts {
530 let txids = (1..num_tx + 1) .map(|i| Txid::from_hex(&format!("{:064x}", i)).unwrap())
533 .collect::<Vec<_>>();
534
535 let hashes = txids.iter().map(|t| t.as_hash());
537 let merkle_root_1: TxMerkleNode = bitcoin_merkle_root(hashes).expect("hashes is not empty").into();
538 let mut height = 1;
539 let mut ntx = num_tx;
540 while ntx > 1 {
541 ntx = (ntx + 1) / 2;
542 height += 1;
543 }
544
545 for att in 1..15 {
547 let mut matches = vec![false; num_tx];
548 let mut match_txid1 = vec![];
549 for j in 0..num_tx {
550 let rand_bits = match att / 2 {
552 0 => 0,
553 bits => rng.gen::<u64>() >> (64 - bits),
554 };
555 let include = rand_bits == 0;
556 matches[j] = include;
557
558 if include {
559 match_txid1.push(txids[j]);
560 };
561 }
562
563 let pmt1 = PartialMerkleTree::from_txids(&txids, &matches);
565 let serialized = serialize(&pmt1);
566
567 let n = min(num_tx, 1 + match_txid1.len() * height);
569 assert!(serialized.len() <= 10 + (258 * n + 7) / 8);
570
571 let pmt2: PartialMerkleTree =
573 deserialize(&serialized).expect("Could not deserialize own data");
574
575 let mut match_txid2: Vec<Txid> = vec![];
577 let mut indexes = vec![];
578 let merkle_root_2 = pmt2
579 .extract_matches(&mut match_txid2, &mut indexes)
580 .expect("Could not extract matches");
581
582 assert_eq!(merkle_root_1, merkle_root_2);
584 assert_ne!(merkle_root_2, TxMerkleNode::default());
585
586 assert_eq!(match_txid1, match_txid2);
588
589 for _ in 0..4 {
591 let mut pmt3: PartialMerkleTree = deserialize(&serialized).unwrap();
592 pmt3.damage(&mut rng);
593 let mut match_txid3 = vec![];
594 let merkle_root_3 = pmt3
595 .extract_matches(&mut match_txid3, &mut indexes)
596 .unwrap();
597 assert_ne!(merkle_root_3, merkle_root_1);
598 }
599 }
600 }
601 }
602
603 #[test]
604 fn pmt_malleability() {
605 let txids: Vec<Txid> = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 9, 10]
607 .iter()
608 .map(|i| Txid::from_hex(&format!("{:064x}", i)).unwrap())
609 .collect();
610
611 let matches = vec![
612 false, false, false, false, false, false, false, false, false, true, true, false,
613 ];
614
615 let tree = PartialMerkleTree::from_txids(&txids, &matches);
616 let result = tree.extract_matches(&mut vec![], &mut vec![]);
618 assert!(result.is_err());
619 }
620
621 #[test]
622 fn merkleblock_serialization() {
623 let mb_hex =
626 "0100000090f0a9f110702f808219ebea1173056042a714bad51b916cb6800000000000005275289558f51c\
627 9966699404ae2294730c3c9f9bda53523ce50e9b95e558da2fdb261b4d4c86041b1ab1bf930900000005fac\
628 7708a6e81b2a986dea60db2663840ed141130848162eb1bd1dee54f309a1b2ee1e12587e497ada70d9bd10d\
629 31e83f0a924825b96cb8d04e8936d793fb60db7ad8b910d0c7ba2369bc7f18bb53d80e1869ba2c32274996c\
630 ebe1ae264bc0e2289189ff0316cdc10511da71da757e553cada9f3b5b1434f3923673adb57d83caac392c38\
631 af156d6fc30b55fad4112df2b95531e68114e9ad10011e72f7b7cfdb025700";
632
633 let mb: MerkleBlock = deserialize(&Vec::from_hex(mb_hex).unwrap()).unwrap();
634 assert_eq!(get_block_13b8a().block_hash(), mb.header.block_hash());
635 assert_eq!(
636 mb.header.merkle_root,
637 mb.txn.extract_matches(&mut vec![], &mut vec![]).unwrap()
638 );
639 assert_eq!(mb_hex, serialize(&mb).to_hex().as_str());
641 }
642
643 #[test]
646 fn merkleblock_construct_from_txids_found() {
647 let block = get_block_13b8a();
648
649 let txids: Vec<Txid> = [
650 "74d681e0e03bafa802c8aa084379aa98d9fcd632ddc2ed9782b586ec87451f20",
651 "f9fc751cb7dc372406a9f8d738d5e6f8f63bab71986a39cf36ee70ee17036d07",
652 ]
653 .iter()
654 .map(|hex| Txid::from_hex(hex).unwrap())
655 .collect();
656
657 let txid1 = txids[0];
658 let txid2 = txids[1];
659 let txids = vec![txid1, txid2];
660
661 let merkle_block = MerkleBlock::from_block_with_predicate(&block, |t| txids.contains(t));
662
663 assert_eq!(merkle_block.header.block_hash(), block.block_hash());
664
665 let mut matches: Vec<Txid> = vec![];
666 let mut index: Vec<u32> = vec![];
667
668 assert_eq!(
669 merkle_block
670 .txn
671 .extract_matches(&mut matches, &mut index)
672 .unwrap(),
673 block.header.merkle_root
674 );
675 assert_eq!(matches.len(), 2);
676
677 assert_eq!(matches[0], txid2);
679 assert_eq!(index[0], 1);
680
681 assert_eq!(matches[1], txid1);
682 assert_eq!(index[1], 8);
683 }
684
685 #[test]
687 fn merkleblock_construct_from_txids_not_found() {
688 let block = get_block_13b8a();
689 let txids: Vec<Txid> = ["c0ffee00003bafa802c8aa084379aa98d9fcd632ddc2ed9782b586ec87451f20"]
690 .iter()
691 .map(|hex| Txid::from_hex(hex).unwrap())
692 .collect();
693
694 let merkle_block = MerkleBlock::from_block_with_predicate(&block, |t| txids.contains(t));
695
696 assert_eq!(merkle_block.header.block_hash(), block.block_hash());
697
698 let mut matches: Vec<Txid> = vec![];
699 let mut index: Vec<u32> = vec![];
700
701 assert_eq!(
702 merkle_block
703 .txn
704 .extract_matches(&mut matches, &mut index)
705 .unwrap(),
706 block.header.merkle_root
707 );
708 assert_eq!(matches.len(), 0);
709 assert_eq!(index.len(), 0);
710 }
711
712 impl PartialMerkleTree {
713 fn damage(&mut self, rng: &mut ThreadRng) {
715 let n = rng.gen_range(0.. self.hashes.len());
716 let bit = rng.gen::<u8>();
717 let hashes = &mut self.hashes;
718 let mut hash = hashes[n].into_inner();
719 hash[(bit >> 3) as usize] ^= 1 << (bit & 7);
720 hashes[n] = TxMerkleNode::from_slice(&hash).unwrap();
721 }
722 }
723
724 fn get_block_13b8a() -> Block {
727 let block_hex =
728 "0100000090f0a9f110702f808219ebea1173056042a714bad51b916cb6800000000000005275289558f51c\
729 9966699404ae2294730c3c9f9bda53523ce50e9b95e558da2fdb261b4d4c86041b1ab1bf930901000000010\
730 000000000000000000000000000000000000000000000000000000000000000ffffffff07044c86041b0146\
731 ffffffff0100f2052a01000000434104e18f7afbe4721580e81e8414fc8c24d7cfacf254bb5c7b949450c3e\
732 997c2dc1242487a8169507b631eb3771f2b425483fb13102c4eb5d858eef260fe70fbfae0ac000000000100\
733 00000196608ccbafa16abada902780da4dc35dafd7af05fa0da08cf833575f8cf9e836000000004a4930460\
734 22100dab24889213caf43ae6adc41cf1c9396c08240c199f5225acf45416330fd7dbd022100fe37900e0644\
735 bf574493a07fc5edba06dbc07c311b947520c2d514bc5725dcb401ffffffff0100f2052a010000001976a91\
736 4f15d1921f52e4007b146dfa60f369ed2fc393ce288ac000000000100000001fb766c1288458c2bafcfec81\
737 e48b24d98ec706de6b8af7c4e3c29419bfacb56d000000008c493046022100f268ba165ce0ad2e6d93f089c\
738 fcd3785de5c963bb5ea6b8c1b23f1ce3e517b9f022100da7c0f21adc6c401887f2bfd1922f11d76159cbc59\
739 7fbd756a23dcbb00f4d7290141042b4e8625a96127826915a5b109852636ad0da753c9e1d5606a50480cd0c\
740 40f1f8b8d898235e571fe9357d9ec842bc4bba1827daaf4de06d71844d0057707966affffffff0280969800\
741 000000001976a9146963907531db72d0ed1a0cfb471ccb63923446f388ac80d6e34c000000001976a914f06\
742 88ba1c0d1ce182c7af6741e02658c7d4dfcd388ac000000000100000002c40297f730dd7b5a99567eb8d27b\
743 78758f607507c52292d02d4031895b52f2ff010000008b483045022100f7edfd4b0aac404e5bab4fd3889e0\
744 c6c41aa8d0e6fa122316f68eddd0a65013902205b09cc8b2d56e1cd1f7f2fafd60a129ed94504c4ac7bdc67\
745 b56fe67512658b3e014104732012cb962afa90d31b25d8fb0e32c94e513ab7a17805c14ca4c3423e18b4fb5\
746 d0e676841733cb83abaf975845c9f6f2a8097b7d04f4908b18368d6fc2d68ecffffffffca5065ff9617cbcb\
747 a45eb23726df6498a9b9cafed4f54cbab9d227b0035ddefb000000008a473044022068010362a13c7f9919f\
748 a832b2dee4e788f61f6f5d344a7c2a0da6ae740605658022006d1af525b9a14a35c003b78b72bd59738cd67\
749 6f845d1ff3fc25049e01003614014104732012cb962afa90d31b25d8fb0e32c94e513ab7a17805c14ca4c34\
750 23e18b4fb5d0e676841733cb83abaf975845c9f6f2a8097b7d04f4908b18368d6fc2d68ecffffffff01001e\
751 c4110200000043410469ab4181eceb28985b9b4e895c13fa5e68d85761b7eee311db5addef76fa862186513\
752 4a221bd01f28ec9999ee3e021e60766e9d1f3458c115fb28650605f11c9ac000000000100000001cdaf2f75\
753 8e91c514655e2dc50633d1e4c84989f8aa90a0dbc883f0d23ed5c2fa010000008b48304502207ab51be6f12\
754 a1962ba0aaaf24a20e0b69b27a94fac5adf45aa7d2d18ffd9236102210086ae728b370e5329eead9accd880\
755 d0cb070aea0c96255fae6c4f1ddcce1fd56e014104462e76fd4067b3a0aa42070082dcb0bf2f388b6495cf3\
756 3d789904f07d0f55c40fbd4b82963c69b3dc31895d0c772c812b1d5fbcade15312ef1c0e8ebbb12dcd4ffff\
757 ffff02404b4c00000000001976a9142b6ba7c9d796b75eef7942fc9288edd37c32f5c388ac002d310100000\
758 0001976a9141befba0cdc1ad56529371864d9f6cb042faa06b588ac000000000100000001b4a47603e71b61\
759 bc3326efd90111bf02d2f549b067f4c4a8fa183b57a0f800cb010000008a4730440220177c37f9a505c3f1a\
760 1f0ce2da777c339bd8339ffa02c7cb41f0a5804f473c9230220585b25a2ee80eb59292e52b987dad92acb0c\
761 64eced92ed9ee105ad153cdb12d001410443bd44f683467e549dae7d20d1d79cbdb6df985c6e9c029c8d0c6\
762 cb46cc1a4d3cf7923c5021b27f7a0b562ada113bc85d5fda5a1b41e87fe6e8802817cf69996ffffffff0280\
763 651406000000001976a9145505614859643ab7b547cd7f1f5e7e2a12322d3788ac00aa0271000000001976a\
764 914ea4720a7a52fc166c55ff2298e07baf70ae67e1b88ac00000000010000000586c62cd602d219bb60edb1\
765 4a3e204de0705176f9022fe49a538054fb14abb49e010000008c493046022100f2bc2aba2534becbdf062eb\
766 993853a42bbbc282083d0daf9b4b585bd401aa8c9022100b1d7fd7ee0b95600db8535bbf331b19eed8d961f\
767 7a8e54159c53675d5f69df8c014104462e76fd4067b3a0aa42070082dcb0bf2f388b6495cf33d789904f07d\
768 0f55c40fbd4b82963c69b3dc31895d0c772c812b1d5fbcade15312ef1c0e8ebbb12dcd4ffffffff03ad0e58\
769 ccdac3df9dc28a218bcf6f1997b0a93306faaa4b3a28ae83447b2179010000008b483045022100be12b2937\
770 179da88599e27bb31c3525097a07cdb52422d165b3ca2f2020ffcf702200971b51f853a53d644ebae9ec8f3\
771 512e442b1bcb6c315a5b491d119d10624c83014104462e76fd4067b3a0aa42070082dcb0bf2f388b6495cf3\
772 3d789904f07d0f55c40fbd4b82963c69b3dc31895d0c772c812b1d5fbcade15312ef1c0e8ebbb12dcd4ffff\
773 ffff2acfcab629bbc8685792603762c921580030ba144af553d271716a95089e107b010000008b483045022\
774 100fa579a840ac258871365dd48cd7552f96c8eea69bd00d84f05b283a0dab311e102207e3c0ee9234814cf\
775 bb1b659b83671618f45abc1326b9edcc77d552a4f2a805c0014104462e76fd4067b3a0aa42070082dcb0bf2\
776 f388b6495cf33d789904f07d0f55c40fbd4b82963c69b3dc31895d0c772c812b1d5fbcade15312ef1c0e8eb\
777 bb12dcd4ffffffffdcdc6023bbc9944a658ddc588e61eacb737ddf0a3cd24f113b5a8634c517fcd20000000\
778 08b4830450221008d6df731df5d32267954bd7d2dda2302b74c6c2a6aa5c0ca64ecbabc1af03c75022010e5\
779 5c571d65da7701ae2da1956c442df81bbf076cdbac25133f99d98a9ed34c014104462e76fd4067b3a0aa420\
780 70082dcb0bf2f388b6495cf33d789904f07d0f55c40fbd4b82963c69b3dc31895d0c772c812b1d5fbcade15\
781 312ef1c0e8ebbb12dcd4ffffffffe15557cd5ce258f479dfd6dc6514edf6d7ed5b21fcfa4a038fd69f06b83\
782 ac76e010000008b483045022023b3e0ab071eb11de2eb1cc3a67261b866f86bf6867d4558165f7c8c8aca2d\
783 86022100dc6e1f53a91de3efe8f63512850811f26284b62f850c70ca73ed5de8771fb451014104462e76fd4\
784 067b3a0aa42070082dcb0bf2f388b6495cf33d789904f07d0f55c40fbd4b82963c69b3dc31895d0c772c812\
785 b1d5fbcade15312ef1c0e8ebbb12dcd4ffffffff01404b4c00000000001976a9142b6ba7c9d796b75eef794\
786 2fc9288edd37c32f5c388ac00000000010000000166d7577163c932b4f9690ca6a80b6e4eb001f0a2fa9023\
787 df5595602aae96ed8d000000008a4730440220262b42546302dfb654a229cefc86432b89628ff259dc87edd\
788 1154535b16a67e102207b4634c020a97c3e7bbd0d4d19da6aa2269ad9dded4026e896b213d73ca4b63f0141\
789 04979b82d02226b3a4597523845754d44f13639e3bf2df5e82c6aab2bdc79687368b01b1ab8b19875ae3c90\
790 d661a3d0a33161dab29934edeb36aa01976be3baf8affffffff02404b4c00000000001976a9144854e695a0\
791 2af0aeacb823ccbc272134561e0a1688ac40420f00000000001976a914abee93376d6b37b5c2940655a6fca\
792 f1c8e74237988ac0000000001000000014e3f8ef2e91349a9059cb4f01e54ab2597c1387161d3da89919f7e\
793 a6acdbb371010000008c49304602210081f3183471a5ca22307c0800226f3ef9c353069e0773ac76bb58065\
794 4d56aa523022100d4c56465bdc069060846f4fbf2f6b20520b2a80b08b168b31e66ddb9c694e24001410497\
795 6c79848e18251612f8940875b2b08d06e6dc73b9840e8860c066b7e87432c477e9a59a453e71e6d76d5fe34\
796 058b800a098fc1740ce3012e8fc8a00c96af966ffffffff02c0e1e400000000001976a9144134e75a6fcb60\
797 42034aab5e18570cf1f844f54788ac404b4c00000000001976a9142b6ba7c9d796b75eef7942fc9288edd37\
798 c32f5c388ac00000000";
799 deserialize(&Vec::from_hex(block_hex).unwrap()).unwrap()
800 }
801}