From db30e53470d8e72ba18dabfd2ac98358fa124ed3 Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Mon, 6 Jul 2020 21:37:32 -0300 Subject: [PATCH] Create a test for block size (#558) * add block size limit test * calculate max_transactions_in_block and max_inputs_in_tx * abstract block generation * move all test vectors to zebra-test --- zebra-chain/src/block.rs | 2 +- zebra-chain/src/block/tests.rs | 85 +++++++++++++++--- zebra-chain/src/lib.rs | 3 + zebra-chain/src/test.rs | 2 + zebra-chain/src/test/generate.rs | 144 +++++++++++++++++++++++++++++++ zebra-test/src/vectors.rs | 4 +- 6 files changed, 225 insertions(+), 15 deletions(-) create mode 100644 zebra-chain/src/test.rs create mode 100644 zebra-chain/src/test/generate.rs diff --git a/zebra-chain/src/block.rs b/zebra-chain/src/block.rs index e73e312f..3ea0545c 100644 --- a/zebra-chain/src/block.rs +++ b/zebra-chain/src/block.rs @@ -41,7 +41,7 @@ pub struct Block { /// in the Zcash specification. (But since blocks also contain a /// block header and transaction count, the maximum size of a /// transaction in the chain is approximately 1.5 kB smaller.) -const MAX_BLOCK_BYTES: u64 = 2_000_000; +pub const MAX_BLOCK_BYTES: u64 = 2_000_000; impl Block { /// Return the block height reported in the coinbase transaction, if any. diff --git a/zebra-chain/src/block/tests.rs b/zebra-chain/src/block/tests.rs index 54456210..8a689311 100644 --- a/zebra-chain/src/block/tests.rs +++ b/zebra-chain/src/block/tests.rs @@ -1,4 +1,4 @@ -use chrono::{DateTime, NaiveDateTime, TimeZone, Utc}; +use chrono::{TimeZone, Utc}; use std::io::{Cursor, ErrorKind, Write}; use proptest::{ @@ -12,6 +12,8 @@ use crate::note_commitment_tree::SaplingNoteTreeRootHash; use crate::serialization::{SerializationError, ZcashDeserialize, ZcashSerialize}; use crate::sha256d_writer::Sha256dWriter; +use crate::test::generate; + use super::*; #[cfg(test)] @@ -74,18 +76,7 @@ fn blockheaderhash_debug() { #[test] fn blockheaderhash_from_blockheader() { - let some_bytes = [0; 32]; - - let blockheader = BlockHeader { - version: 4, - previous_block_hash: BlockHeaderHash(some_bytes), - merkle_root_hash: MerkleTreeRootHash(some_bytes), - final_sapling_root_hash: SaplingNoteTreeRootHash(some_bytes), - time: DateTime::::from_utc(NaiveDateTime::from_timestamp(61, 0), Utc), - bits: 0, - nonce: some_bytes, - solution: EquihashSolution([0; 1344]), - }; + let blockheader = generate::block_header(); let hash = BlockHeaderHash::from(&blockheader); @@ -130,6 +121,74 @@ fn deserialize_block() { .expect("block test vector should deserialize"); } +#[test] +fn block_limits_multi_tx() { + // Test multiple small transactions to fill a block max size + + // Create a block just below the limit + let mut block = generate::large_multi_transaction_block(); + + // Serialize the block + let mut data = Vec::new(); + block + .zcash_serialize(&mut data) + .expect("block should serialize as we are not limiting generation yet"); + + assert!(data.len() <= MAX_BLOCK_BYTES as usize); + + // Deserialize by now is ok as we are lower than the limit + let block2 = Block::zcash_deserialize(&data[..]) + .expect("block should deserialize as we are just below limit"); + assert_eq!(block, block2); + + // Add 1 more transaction to the block, limit will be reached + block = generate::oversized_multi_transaction_block(); + + // Serialize will still be fine + let mut data = Vec::new(); + block + .zcash_serialize(&mut data) + .expect("block should serialize as we are not limiting generation yet"); + + assert!(data.len() > MAX_BLOCK_BYTES as usize); + + // Deserialize will now fail + Block::zcash_deserialize(&data[..]).expect_err("block should not deserialize"); +} + +#[test] +fn block_limits_single_tx() { + // Test block limit with a big single transaction + + // Create a block just below the limit + let mut block = generate::large_single_transaction_block(); + + // Serialize the block + let mut data = Vec::new(); + block + .zcash_serialize(&mut data) + .expect("block should serialize as we are not limiting generation yet"); + + assert!(data.len() <= MAX_BLOCK_BYTES as usize); + + // Deserialize by now is ok as we are lower than the limit + Block::zcash_deserialize(&data[..]) + .expect("block should deserialize as we are just below limit"); + + // Add 1 more input to the transaction, limit will be reached + block = generate::oversized_single_transaction_block(); + + let mut data = Vec::new(); + block + .zcash_serialize(&mut data) + .expect("block should serialize as we are not limiting generation yet"); + + assert!(data.len() > MAX_BLOCK_BYTES as usize); + + // Will fail as block overall size is above limit + Block::zcash_deserialize(&data[..]).expect_err("block should not deserialize"); +} + proptest! { #[test] diff --git a/zebra-chain/src/lib.rs b/zebra-chain/src/lib.rs index c070606e..3e8dcad8 100644 --- a/zebra-chain/src/lib.rs +++ b/zebra-chain/src/lib.rs @@ -29,6 +29,9 @@ pub use redjubjub; #[cfg(test)] use proptest_derive::Arbitrary; +#[cfg(test)] +pub mod test; + /// An enum describing the possible network choices. #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)] #[cfg_attr(test, derive(Arbitrary))] diff --git a/zebra-chain/src/test.rs b/zebra-chain/src/test.rs new file mode 100644 index 00000000..c2e4254c --- /dev/null +++ b/zebra-chain/src/test.rs @@ -0,0 +1,2 @@ +//! Test support code +pub mod generate; diff --git a/zebra-chain/src/test/generate.rs b/zebra-chain/src/test/generate.rs new file mode 100644 index 00000000..c7e73b82 --- /dev/null +++ b/zebra-chain/src/test/generate.rs @@ -0,0 +1,144 @@ +//! Generate blockchain testing constructions +use chrono::{DateTime, NaiveDateTime, Utc}; +use std::sync::Arc; + +use crate::{ + block::{Block, BlockHeader, BlockHeaderHash, MAX_BLOCK_BYTES}, + equihash_solution::EquihashSolution, + merkle_tree::MerkleTreeRootHash, + note_commitment_tree::SaplingNoteTreeRootHash, + serialization::{ZcashDeserialize, ZcashSerialize}, + transaction::{Transaction, TransparentInput, TransparentOutput}, + types::LockTime, +}; + +/// Generate a block header +pub fn block_header() -> BlockHeader { + let some_bytes = [0; 32]; + BlockHeader { + version: 4, + previous_block_hash: BlockHeaderHash(some_bytes), + merkle_root_hash: MerkleTreeRootHash(some_bytes), + final_sapling_root_hash: SaplingNoteTreeRootHash(some_bytes), + time: DateTime::::from_utc(NaiveDateTime::from_timestamp(61, 0), Utc), + bits: 0, + nonce: some_bytes, + solution: EquihashSolution([0; 1344]), + } +} + +/// Generate a block with multiple transactions just below limit +pub fn large_multi_transaction_block() -> Block { + multi_transaction_block(false) +} + +/// Generate a block with one transaction and multiple inputs just below limit +pub fn large_single_transaction_block() -> Block { + single_transaction_block(false) +} + +/// Generate a block with multiple transactions just above limit +pub fn oversized_multi_transaction_block() -> Block { + multi_transaction_block(true) +} + +/// Generate a block with one transaction and multiple inputs just above limit +pub fn oversized_single_transaction_block() -> Block { + single_transaction_block(true) +} + +// Implementation of block generation with multiple transactions +fn multi_transaction_block(oversized: bool) -> Block { + // A dummy transaction + let tx = Transaction::zcash_deserialize(&zebra_test::vectors::DUMMY_TX1[..]).unwrap(); + + // A block header + let blockheader = block_header(); + + // Serialize header + let mut data_header = Vec::new(); + blockheader + .zcash_serialize(&mut data_header) + .expect("Block header should serialize"); + + // Calculate the number of transactions we need + let mut max_transactions_in_block = + (MAX_BLOCK_BYTES as usize - data_header.len()) / *&zebra_test::vectors::DUMMY_TX1[..].len(); + if oversized { + max_transactions_in_block = max_transactions_in_block + 1; + } + + // Create transactions to be just below or just above the limit + let many_transactions = std::iter::repeat(Arc::new(tx.clone())) + .take(max_transactions_in_block) + .collect::>(); + + // Add the transactions into a block + Block { + header: blockheader, + transactions: many_transactions, + } +} + +// Implementation of block generation with one transaction and multiple inputs +fn single_transaction_block(oversized: bool) -> Block { + // Dummy input and output + let input = + TransparentInput::zcash_deserialize(&zebra_test::vectors::DUMMY_INPUT1[..]).unwrap(); + let output = + TransparentOutput::zcash_deserialize(&zebra_test::vectors::DUMMY_OUTPUT1[..]).unwrap(); + + // A block header + let blockheader = block_header(); + + // Serialize header + let mut data_header = Vec::new(); + blockheader + .zcash_serialize(&mut data_header) + .expect("Block header should serialize"); + + // Serialize a LockTime + let locktime = LockTime::Time(DateTime::::from_utc( + NaiveDateTime::from_timestamp(61, 0), + Utc, + )); + let mut data_locktime = Vec::new(); + locktime + .zcash_serialize(&mut data_locktime) + .expect("LockTime should serialize"); + + // Calculate the number of inputs we need + let mut max_inputs_in_tx = (MAX_BLOCK_BYTES as usize + - data_header.len() + - *&zebra_test::vectors::DUMMY_OUTPUT1[..].len() + - data_locktime.len()) + / (*&zebra_test::vectors::DUMMY_INPUT1[..].len() - 1); + + if oversized { + max_inputs_in_tx = max_inputs_in_tx + 1; + } + + let mut outputs = Vec::new(); + + // Create inputs to be just below the limit + let inputs = std::iter::repeat(input.clone()) + .take(max_inputs_in_tx) + .collect::>(); + + // 1 single output + outputs.push(output); + + // Create a big transaction + let big_transaction = Transaction::V1 { + inputs: inputs.clone(), + outputs: outputs.clone(), + lock_time: locktime, + }; + + // Put the big transaction into a block + let transactions = vec![Arc::new(big_transaction.clone())]; + Block { + header: blockheader, + transactions: transactions.clone(), + } +} diff --git a/zebra-test/src/vectors.rs b/zebra-test/src/vectors.rs index 51a2cea5..efa9fdcd 100644 --- a/zebra-test/src/vectors.rs +++ b/zebra-test/src/vectors.rs @@ -238,6 +238,9 @@ lazy_static! { pub static ref BLOCK_MAINNET_GENESIS_BYTES: Vec = >::from_hex("040000000000000000000000000000000000000000000000000000000000000000000000db4d7a85b768123f1dff1d4c4cece70083b2d27e117b4ac2e31d087988a5eac4000000000000000000000000000000000000000000000000000000000000000090041358ffff071f5712000000000000000000000000000000000000000000000000000000000000fd4005000a889f00854b8665cd555f4656f68179d31ccadc1b1f7fb0952726313b16941da348284d67add4686121d4e3d930160c1348d8191c25f12b267a6a9c131b5031cbf8af1f79c9d513076a216ec87ed045fa966e01214ed83ca02dc1797270a454720d3206ac7d931a0a680c5c5e099057592570ca9bdf6058343958b31901fce1a15a4f38fd347750912e14004c73dfe588b903b6c03166582eeaf30529b14072a7b3079e3a684601b9b3024054201f7440b0ee9eb1a7120ff43f713735494aa27b1f8bab60d7f398bca14f6abb2adbf29b04099121438a7974b078a11635b594e9170f1086140b4173822dd697894483e1c6b4e8b8dcd5cb12ca4903bc61e108871d4d915a9093c18ac9b02b6716ce1013ca2c1174e319c1a570215bc9ab5f7564765f7be20524dc3fdf8aa356fd94d445e05ab165ad8bb4a0db096c097618c81098f91443c719416d39837af6de85015dca0de89462b1d8386758b2cf8a99e00953b308032ae44c35e05eb71842922eb69797f68813b59caf266cb6c213569ae3280505421a7e3a0a37fdf8e2ea354fc5422816655394a9454bac542a9298f176e211020d63dee6852c40de02267e2fc9d5e1ff2ad9309506f02a1a71a0501b16d0d36f70cdfd8de78116c0c506ee0b8ddfdeb561acadf31746b5a9dd32c21930884397fb1682164cb565cc14e089d66635a32618f7eb05fe05082b8a3fae620571660a6b89886eac53dec109d7cbb6930ca698a168f301a950be152da1be2b9e07516995e20baceebecb5579d7cdbc16d09f3a50cb3c7dffe33f26686d4ff3f8946ee6475e98cf7b3cf9062b6966e838f865ff3de5fb064a37a21da7bb8dfd2501a29e184f207caaba364f36f2329a77515dcb710e29ffbf73e2bbd773fab1f9a6b005567affff605c132e4e4dd69f36bd201005458cfbd2c658701eb2a700251cefd886b1e674ae816d3f719bac64be649c172ba27a4fd55947d95d53ba4cbc73de97b8af5ed4840b659370c556e7376457f51e5ebb66018849923db82c1c9a819f173cccdb8f3324b239609a300018d0fb094adf5bd7cbb3834c69e6d0b3798065c525b20f040e965e1a161af78ff7561cd874f5f1b75aa0bc77f720589e1b810f831eac5073e6dd46d00a2793f70f7427f0f798f2f53a67e615e65d356e66fe40609a958a05edb4c175bcc383ea0530e67ddbe479a898943c6e3074c6fcc252d6014de3a3d292b03f0d88d312fe221be7be7e3c59d07fa0f2f4029e364f1f355c5d01fa53770d0cd76d82bf7e60f6903bc1beb772e6fde4a70be51d9c7e03c8d6d8dfb361a234ba47c470fe630820bbd920715621b9fbedb49fcee165ead0875e6c2b1af16f50b5d6140cc981122fcbcf7c5a4e3772b3661b628e08380abc545957e59f634705b1bbde2f0b4e055a5ec5676d859be77e20962b645e051a880fddb0180b4555789e1f9344a436a84dc5579e2553f1e5fb0a599c137be36cabbed0319831fea3fddf94ddc7971e4bcf02cdc93294a9aab3e3b13e3b058235b4f4ec06ba4ceaa49d675b4ba80716f3bc6976b1fbf9c8bf1f3e3a4dc1cd83ef9cf816667fb94f1e923ff63fef072e6a19321e4812f96cb0ffa864da50ad74deb76917a336f31dce03ed5f0303aad5e6a83634f9fcc371096f8288b8f02ddded5ff1bb9d49331e4a84dbe1543164438fde9ad71dab024779dcdde0b6602b5ae0a6265c14b94edd83b37403f4b78fcd2ed555b596402c28ee81d87a909c4e8722b30c71ecdd861b05f61f8b1231795c76adba2fdefa451b283a5d527955b9f3de1b9828e7b2e74123dd47062ddcc09b05e7fa13cb2212a6fdbc65d7e852cec463ec6fd929f5b8483cf3052113b13dac91b69f49d1b7d1aec01c4a68e41ce1570101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff071f0104455a6361736830623963346565663862376363343137656535303031653335303039383462366665613335363833613763616331343161303433633432303634383335643334ffffffff010000000000000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000").expect("Block bytes are in valid hex representation"); pub static ref BLOCK_MAINNET_1_BYTES: Vec = >::from_hex("0400000008ce3d9731b000c08338455c8a4a6bd05da16e26b11daa1b917184ece80f04000946edb9c083c9942d92305444527765fad789c438c717783276a9f7fbf61b850000000000000000000000000000000000000000000000000000000000000000ac7a1358ffff071f7534e8cf161ff2e49d54bdb3bfbcde8cdbf2fc5963c9ec7d86aed4a67e975790fd4005002b2ee0d2f5d0c1ebf5a265b6f5b428f2fdc9aaea07078a6c5cab4f1bbfcd56489863deae6ea3fd8d3d0762e8e5295ff2670c9e90d8e8c68a54a40927e82a65e1d44ced20d835818e172d7b7f5ffe0245d0c3860a3f11af5658d68b6a7253b4684ffef5242fefa77a0bfc3437e8d94df9dc57510f5a128e676dd9ddf23f0ef75b460090f507499585541ab53a470c547ea02723d3a979930941157792c4362e42d3b9faca342a5c05a56909b046b5e92e2870fca7c932ae2c2fdd97d75b6e0ecb501701c1250246093c73efc5ec2838aeb80b59577741aa5ccdf4a631b79f70fc419e28714fa22108d991c29052b2f5f72294c355b57504369313470ecdd8e0ae97fc48e243a38c2ee7315bb05b7de9602047e97449c81e46746513221738dc729d7077a1771cea858865d85261e71e82003ccfbba2416358f023251206d6ef4c5596bc35b2b5bce3e9351798aa2c9904723034e5815c7512d260cc957df5db6adf9ed7272483312d1e68c60955a944e713355089876a704aef06359238f6de5a618f7bd0b4552ba72d05a6165e582f62d55ff2e1b76991971689ba3bee16a520fd85380a6e5a31de4dd4654d561101ce0ca390862d5774921eae2c284008692e9e08562144e8aa1f399a9d3fab0c4559c1f12bc945e626f7a89668613e8829767f4116ee9a4f832cf7c3ade3a7aba8cb04de39edd94d0d05093ed642adf9fbd9d373a80832ffd1c62034e4341546b3515f0e42e6d8570393c6754be5cdb7753b4709527d3f164aebf3d315934f7b3736a1b31052f6cc5699758950331163b3df05b9772e9bf99c8c77f8960e10a15edb06200106f45742d740c422c86b7e4f5a52d3732aa79ee54cfc92f76e03c268ae226477c19924e733caf95b8f350233a5312f4ed349d3ad76f032358f83a6d0d6f83b2a456742aad7f3e615fa72286300f0ea1c9793831ef3a5a4ae08640a6e32f53d1cba0be284b25e923d0d110ba227e54725632efcbbe17c05a9cde976504f6aece0c461b562cfae1b85d5f6782ee27b3e332ac0775f681682ce524b32889f1dc4231226f1aada0703beaf8d41732c9647a0a940a86f8a1be7f239c44fcaa7ed7a055506bdbe1df848f9e047226bee1b6d788a03f6e352eead99b419cfc41741942dbeb7a5c55788d5a3e636d8aab7b36b4db71d16700373bbc1cdeba8f9b1db10bf39a621bc737ea4f4e333698d6e09b51ac7a97fb6fd117ccad1d6b6b3a7451699d5bfe448650396d7b58867b3b0872be13ad0b43da267df0ad77025155f04e20c56d6a9befb3e9c7d23b82cbf3a534295ebda540682cc81be9273781b92519c858f9c25294fbacf75c3b3c15bda6d36de1c83336f93e96910dbdcb190d6ef123c98565ff6df1e903f57d4e4df167ba6b829d6d9713eb2126b0cf869940204137babcc6a1b7cb2f0b94318a7460e5d1a605c249bd2e72123ebad332332c18adcb285ed8874dbde084ebcd4f744465350d57110f037fffed1569d642c258749e65b0d13e117eaa37014a769b5ab479b7c77178880e77099f999abe712e543dbbf626ca9bcfddc42ff2f109d21c8bd464894e55ae504fdf81e1a7694180225da7dac8879abd1036cf26bb50532b8cf138b337a1a1bd1a43f8dd70b7399e2690c8e7a5a1fe099026b8f2a6f65fc0dbedda15ba65e0abd66c7176fb426980549892b4817de78e345a7aeab05744c3def4a2f283b4255b02c91c1af7354a368c67a11703c642a385c7453131ce3a78b24c5e22ab7e136a38498ce82082181884418cb4d6c2920f258a3ad20cfbe7104af1c6c6cb5e58bf29a9901721ad19c0a260cd09a3a772443a45aea4a5c439a95834ef5dc2e26343278947b7b796f796ae9bcadb29e2899a1d7313e6f7bfb6f8b0101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff025100ffffffff0250c30000000000002321027a46eb513588b01b37ea24303f4b628afd12cc20df789fede0921e43cad3e875acd43000000000000017a9147d46a730d31f97b1930d3368a967c309bd4d136a8700000000").expect("Block bytes are in valid hex representation"); pub static ref BLOCK_MAINNET_434873_BYTES: Vec = >::from_hex("0000002095f4f680b726de8a0a1fe2e77bb52acf0f959b46e4f035fc40165001000000004cf8f74f6a426819cbc390bf99f8c53b941bd57861fa5a3376c2091b7971e3b017951a08906ff5feaf33ff2fd1a148121035db654ad224cb46d141bc9931e3561770fa5b16c1021c5c0c0000000000005000316c000000000000e000000000000000000000000000fd40050049085037233d9f7c61722324a6e4bafee15e242442e7fcaaec6f0cf1dfbbd77806f50a5e97f4d9f44707d6c5221bd30005309a9150b1f24d6d8823f6bea70f4f346b5319427fb817818d796c85538fefbd8473005e3bdfab42c2d1792fe5af6bc77091f25a5e08ca08e0ee142c1ff1a3e8cc70bb7e37f02e7b7f9e886b1d43c128fcd7c62db3a52a156febb96bcd0b1e7c685047adb2c91a2a150fd656b628eefe2627adfb9f1400e0813df3ed3bb1bde000b482dc325925f3188aff15939e07fb88faa92b86c50f4f36ea49e33b121049031815dc03d2a4b7ec4cd1d638a5dd02a386deb9001bafe95b5e0f99c0fd77f8718a472442449a1f79a70e3828ac216b361d6360d115ffd2534de05f1b0148213d7c03855874eb7d32a314d4ca3811bd8a31d1df300ad2030d91e0a743b1c48d89bd4bd52e9c76f3ad523d9f38b05ea21b37ce5860e179fd638d53df294c00b233ee220948b17ffd52e960da5428ca1c0cdaa166343cce2adca2399f06b7daa5d3cc567d30b828fe2a759b6459de8131b1ce5303dbc7cde566042e4ae5370064f6979b3bffdecfb5062ede79aea13dd5daad06676bb2d79498117274381fd462871a33bf14be223d521d303cdd9d81f603c62be9665ff59f07f5b14316468f07d9618817cf83416e47e9458e139ebac17e29e0c26abccf4e5d5985c595cbec0ad59229377f61071e02e8930770db42b402dc577f6ca0cf67bbad202f304e5694d8d726f734246608ee5ec537fa0b40d30cd983078ccac691b92fb79f22f819536e849d90ef0ecf94d37611f6074590529f5ffbc0dd2f0b9cfdfd0d5e2207360ce47671d9a31fc22b1f0d2b356e6b1628dd0aa7addd2a97a8179382527196fd64e9f09b4114833b1a6527959f7afb93244e6151fdb0b55df19441c0edb09f134b4917104bec066109bb88455d2e2600688a3a3c16001f0a5ee34bc2a67681b19af7641c25377acffb197551ccf2e3d7963f1d7b13485a8d52337a3ea412d2ba61a0f0240b0f5c083a7ba519850435409bed99aeba357609b4e8cda7bae15f9ff5415b0af751f1c5ddeca3383f922dc5fea935f02b76980b0fd06c0c812f3df381b0c15c1be8f89763c6bc45740c401c79c293ec25ea0c058e16b835a5bba4787a1d0cbb08e6c50cc91aea9eb0cdc86c113c77ea9c45d70236ce2ddf0cd1918d4435b51e467cca574ad9c234095a005d60ce9355eff1a93d857eacdec081fe8ed2097bd2d40e984b9341d543257d7a5fcd1f2abf15f61a014c16560f2806e34ec49113d2ee2a019bd0fd940891d50675f11501c3adb17b2d98ecc4d31c4a4cf52553bfa1fe597785abbc035e296ecb2d967453d7ba26b8cca5e6d55896fa23c3e34c39671a7e21bce2c34316af81b8dfdcb9dc2ac48434eced639f45bff32500edf3a5c24bc3fdba70c3af589eccfb2554f9e7873006136ceb9262b5161413da02408306c3b19712ef0a2f2f11ad86b363d5b3543efc7d46056a2d5e78f5339fbb8319928bbec642e7e1fed2b88ead85dd0b0c03c50ea9e74f1213b980d5e43ee4d96a83787463a3264456b3961816e1349c7ad78f79c70b5952bd66980e8f86b9fd8e18ef6ac43187e8d0774a52f5f5118d1e5a35327510ee2ec0b0b74025ebaf660428d37a2809498ebb1f6c1fd3888f76c9c7d4ce7e189a9a82d73d935af8f93732d3e4a127361d6b9d760363d9df6c10d260a303c880792bcef6bc09e1d332493353779826ebce92f19ec8b13beaa2bd8da15b72c06d7c693916509c87a51a769f084611bbeabd60e9d54dd1bc3b5b578d7754e875c77351865c3ee408eec0e2fadcba18342d2a048f3d2feb9108dc1c5486d30f4c7f29a845c84c72fb58491f03afc6f8cbc2c44ace24dc51b00c0400008085202f89010000000000000000000000000000000000000000000000000000000000000000ffffffff1c03b9a206174d696e656420627920416e74506f6f6c2087205bfa7017ffffffff0280b2e60e0000000017a9144fd89a8512e083965f79d92eb1019f850acee5ec87ad769c3b000000001976a914abe7f622bee66b2761c446167723cbc74f02756588ac000000000000000000000000000000000000000400008085202f890135876168b13fd0b61281f9a117035c8fa0263b05ddc5e17561d03bfea7363497000000006a4730440220165d398beba90238c40aac95d5b78be68d090ee8104ec77634e84cc0d9e85a680220278382ffec60b95bc7b52fd379198c3fb608bbb5936d9b6453d8c558245565de0121036120b78294acc5c63b2c15efbbba01b8947d68a6c65a6273a4ce318bcedd2207feffffff02b2801e15530000001976a91405bbbbac7a0a45101ecf637bc1556986f8a37f3f88ace028933b000000001976a91453548b070f951d500039fae96f1a6162b0cf00b988acaea20600cda2060000000000000000000000000400008085202f89115ace17f622d6656e38fed1c1102c8cc62a411e81f5b8404174952d2588e57c3e090000006b483045022100e2a601492b245ff7f14ca3b014ac1ac61ff19e4f346d1f6eacc5aedeba1e506a02203765f41d3b3bc97845e6af67106c6831a56480c49ffffacf56a3390ffd7ae52c0121028f566fdfd99ff14057d5ef953b31cca6944d5dd33f008e6e2cef3ffc7764408affffffff727f26494145ca762dabfc2f58e736df82ac7286ff0aaca4c2d8bc6eff57a8eb070000006a4730440220123ae3a8cd7215a6e420b1b187155bb3115d76a772c92d8435ea86adfe60a7fc02201fba3fc607360a51d9dfb78c7f30020d481441492a94332397cb18f7c49edbb70121028f566fdfd99ff14057d5ef953b31cca6944d5dd33f008e6e2cef3ffc7764408affffffff25298416a43e5641fac7c9e5947ec4f0e1d5e599d68a37628220157f114f4e5e2e0000006a4730440220125125f326d93eb9adba6cb2d95440d14da4e1b74e29296c7c893a5b0f2ae3b9022042687c05b29f1dc9424f68eba1111f6cce95c14b6ce79ad6b0538ceee69e53e20121028f566fdfd99ff14057d5ef953b31cca6944d5dd33f008e6e2cef3ffc7764408affffffff7059b11d6810c760103de0676ae1ea56339c87d8f9e00e31d9235a8690aa7f001b0000006b483045022100c29aebd7c7d89d4bb4d05733b178ad1e73d6090c35cde800f1c796bbf22b3af302200c6d0fa7692840513781cdf3eb849b159f5e269b00b45a5c07f785d3ef6c23190121028f566fdfd99ff14057d5ef953b31cca6944d5dd33f008e6e2cef3ffc7764408affffffff9221f8e63ae155da79301915067d0e3e384c20460a974cb0041cd14ef2bc85741b0000006b483045022100930eceb70ee7f0eb81d4c004eb1cee3f74464e77d7034f3dc0169cbcae3f66a002204e5eb9d1ae3ec1ad4301eac9ddfc23b5af24781e3a4500376585740fb6e07e5a0121028f566fdfd99ff14057d5ef953b31cca6944d5dd33f008e6e2cef3ffc7764408affffffffc7137b2498c9d2c76799d5a1419c3485b7c60227ef92947289d143d1bc52a411150000006b483045022100daa6e27a5565c5049d3e93907e17416e8abbfc740e1dec1abb642a099f7d5f4d0220016bc838eedb2aa72682634cac3f1614bcf2b04783736a45baf72da5a34327630121028f566fdfd99ff14057d5ef953b31cca6944d5dd33f008e6e2cef3ffc7764408affffffff55f710fdffe710a1f1d7631b5aa6dcdb33ebdfe14da04f7e2e86e81aee4e42da170000006b483045022100e9c0809b72378081f78f42da7f31e3388d33d458e785247cf042a1c1cb15468f02204fbff2679246f3ff48626a3aed15aaa913ddac7f17c026f396296e696deee0fd0121028f566fdfd99ff14057d5ef953b31cca6944d5dd33f008e6e2cef3ffc7764408affffffffbfd294026fc4ba55b49262add6abfd93eaf54eb127cf10bf3172065c6481c59b380000006b483045022100f5074841a60d85561fdb8c147d64792e35091ee180c3e65cce714656d0b67184022025222c98a8f44621e8ea4b3483bc2546d47ae3352059e5fdd15b36a6733d0c1b0121028f566fdfd99ff14057d5ef953b31cca6944d5dd33f008e6e2cef3ffc7764408afffffffff5ae8eb7782733919e0575807fa037e98bd5b4e3cf38c8898f515cf855c06b931a0000006a47304402200a9a2c7184ec37ef9a3c76188f018c0a8cc5ffc25a78e098d5dd87a5478c620002206c97bc7d169075e5ce4ff29141ec4673debb8753e302f02442b1e163ea864a0d0121028f566fdfd99ff14057d5ef953b31cca6944d5dd33f008e6e2cef3ffc7764408afffffffff29dbaa351d0c813831a9572c07fc6fe5b35af25f27c870555210e47d2444e53060000006a4730440220593c95cf370ed68302e98ff8217338af7a54dee8f9864bf974a3c043f7fcf6b502206d7cdea1a55ff43baed5b52c4492426508b074a07da54b86f633d2d238c926b50121028f566fdfd99ff14057d5ef953b31cca6944d5dd33f008e6e2cef3ffc7764408affffffffff134ba21417da9a4d34854c8c35d20b9b4e77e52c06d6b48c3a99c632d11c34260000006a4730440220405a409019d112b620721cf33d7e51aac6cf5fa85daf4674e9dd4e722bae27ae02200d747f8e07cbb91975e5c04fd75130bcf49c0d28ca34384079e27b180dc731740121028f566fdfd99ff14057d5ef953b31cca6944d5dd33f008e6e2cef3ffc7764408afffffffff6e044cfde662d269003d71f3ed4356e16aecf88da75e7dadae9c8b0d3e7fea9060000006b483045022100902e1bc1108e5f0f63b9c248df39887c5c3e34097e972439f2201980dd62038502204e2e0a0f49aeb266be58155d6cc7ed698de80d2ca4b521861e87529849d59c800121028f566fdfd99ff14057d5ef953b31cca6944d5dd33f008e6e2cef3ffc7764408affffffff33ced214ff3d86791c56d0af7ee3a4de84ce0eac96fd96b887b45f19847e4ae9190000006a4730440220159f450f7c2dc56519fab1b0665962b51d497063da1a59e9657df9cbb741a281022032e97a21d19bda1f91c5e2db38b33c7ed77877e1f0c2adcfe14bf2f50da9b5520121028f566fdfd99ff14057d5ef953b31cca6944d5dd33f008e6e2cef3ffc7764408affffffff810e65c127749164b24a605960429a97b8570e347055d689d998169bf5150428000000006b483045022100f19c5516c0615436707f5e68b190a88bf6c5fefd99e932a18bf9e4cfa6f5212c02207df137b0df6cac24ba87170282ff8682a3062b64b7febde51255fb23747403c00121024b19c8b5d932a646f27db45992333eb1cf1cefef8739ce96ff718901176c5c29ffffffff27ba241a39e1b20eab40c56143ee50c3cbca75ae60656c85dbc488de00173adf170000006a47304402205d663644f03d334c589d0abeb91d01bacbf36e2de822eeb3c9f2c5deb45da7a702205e134fcb6a024dbf94881d0b610377edae3d2a1ec2f921631134e8ffee6881b90121028f566fdfd99ff14057d5ef953b31cca6944d5dd33f008e6e2cef3ffc7764408affffffff4132869188b0ccfa2afef66257c0df0f96c8ad99abdc5ae1eadf25708cc5ad300f0000006a47304402200efbec7df701e560b45e7a920cb4d401dec7f0c3439423aab5acde67fee16eb002201f3ec1eeb08b0aa8641079bdda3f63157e08ceebc0623a9c68f73f42556a78a90121028f566fdfd99ff14057d5ef953b31cca6944d5dd33f008e6e2cef3ffc7764408affffffffa18e350fdabd5ee9e2feef3e250b94e01897bff1d01f329de81b49c33b023430110000006a47304402206c0ef6738dbfc2636d4a5a1a890d2dc02cd4b83d63c9ebc8a8f84cb797f892dd0220367cb2c26421537466d3f09a00688efbcd1000708ee43921df492c5bf20cb1120121028f566fdfd99ff14057d5ef953b31cca6944d5dd33f008e6e2cef3ffc7764408affffffff01fdaa5b0a000000001976a914fa4384c589ac8cd35370431f90cc669cb825642c88ac000000000000000000000000000000000000000400008085202f8901ac4e3bb66d7e9064fcb5ab1855bc7ef959313ac36c95792f628a4340c70626d8000000006a4730440220044775c6545d7ec31db0502d51d805684853b2f1817efbfcc97eb1bd1b66f13b02201ca910479b5ad9260b29bd53699b12f897937aa0978342c32e8116de4bbf7f480121025ac9f95eb625cbff0616440e17ef7a442ae536d2aa39268d130cc7732ea7700ffeffffff02bc7b60590c0000001976a914e62bf5200512759a8a6375e35c55f2d42127be3888ac00b3d409000000001976a914706acde3aa0e44659824fa4fdb43a9db2f22b17888acaea20600cda2060000000000000000000000000400008085202f890491d4bda1a1cc6313552965afad66f2f9fd4ecc0cac7d23666261568e26a569ba000000006a473044022069deb712d4762b845e3e1886a5fbddcdc312479d329e5d7aa9dc4e34f4ff5e170220140899d4150c376e0e8b1b6db7f2a7f7dfe05a8dcb0c8bdf5c797282ad9add0e0121022e4cd0e959062d95eb79f797689f48168624b1cc144be6c4b18ec593096b276fffffffffc7bc38f1eb19ce4bbb1042c58d069631fa4b169594eb72c1a7cc0ecfa5dec5c0000000006b4830450221009f831aac45c02e5d02508f12776578ee1d3c3f8d6ed54651db3fdf19ff55c9b902207953ae493c3fcccb18ccf944af3215060e412f7de30356fe0520882281e9729c012103900b40c2a4f21a87df16b169d98834174833f62f65cde5e1fa0b88e121b53097ffffffff224a03167565c57f303945cf2fe68cb9b00091326f7f0e9793d1c645e883c619000000006b483045022100b46c08795e52047797608d58b42bb82964ed87dee569b992e13d99c8ccca76730220223c4813b782e622093715acd2801cd6cc569a9ccb19b0f4b4b76a157208a2570121034c88cf59a41ff7082bb2fd55bdb700373f7d3166c542f683ba110d3f95ae86fcffffffff9e0a2842454f5037a8a9fec0df41119bb5cf35a1ed30282bc46a65e02787d11c000000006b483045022100c9e2dad60bc2886e6de6c0c04184253c73d77e52bdc62309008b7c24493f164802204c153c973e32abf780408b1a62ea78198a35235559ab4afac0151ed1d65490cb012102ad2ed643b71290ce0d496df39d2e7ede9c17786e6bbecf3fc87c7ce3e74bdf9dffffffff0167060753000000001976a91496dfa3baf6bd8d6a9d063bc21dab6f9b89af782388ac000000000000000000000000000000000000000400008085202f89011becd211cd5c56207d74d77a2fecd9a7797fedf92ee89ec0952e6a2a98f5eb2f010000006a473044022041c474323521be2ee5cdaec25003fb5c536d72f32c0b4e186ac0fa8f5cb3467702205759b9a0f162a1f2afc7e7d77db13aced5c5233844779743784163a228272c910121029cf995fbec5950eefb19ad42d6575eb5752bcbf270d620d2153d6ec15a652410ffffffff02809245070000000017a9146f0bf9400d728251ad20ab4e14fd3affd335b53c87145c514e000000001976a9143e63cb144993bc8aa429110ea0bee39b4fbd9e3d88ac000000000000000000000000000000000000000400008085202f89012fbdfd02b15318cc8bb35e44773febbf025408a477e3788ffce515f382a5c0ad020000006b483045022100b6e74e80d6982c41f33f3755c39e5200c3fd089987aec9a20e6a14f819c75cce022061f71e9ba793031c468a08213378be021c689dab28935646802aaa65dfbc25fc012103cfaeaebca2cebf7ca013845caca9dadd21421c2fcf951f2f602b1022a201f635ffffffff0209a33602000000001976a914f66b82b3b5a4244c289b871ff674f97706bf688688ac99412c04000000001976a9141c1c3ce2a149caad4085310646518a76e39df67d88ac00000000cda2060000000000000000000000000400008085202f8902224a03167565c57f303945cf2fe68cb9b00091326f7f0e9793d1c645e883c619010000006a473044022078314b582678d9d0c018445e58c8afa561a151dffbf60cee86627153218d703e02207a20a0aeae7d43922b4b81d50d00de11f2911d26c831520a16e7569cdc4b34260121033aa706b444f605bef8a95023b836cc5217d0a02b70361a7656272ae131bc2050ffffffff6be50ba74e89e64b09664718a138d13e960dbfa6a1bd009e65c64bb7b36a53fb010000006a47304402203fb3f3dcedf8a69e8591e01708b2d068c46e449c02e4904f49e7a173adadd4af022077d45458c8d4bda178b5a3b2d127ee42cc445e35d876d6ac407ca71bd9a5306f012103ed85aa3aa5f144a74565b058e6bf86f7743f207b94fc195cea4e38c1edd11f94ffffffff02802b530b000000001976a914cc0ca0d1a3b4d1e440c981cadddb0f0eecf6cb3888acbefc7448000000001976a914f7f5cbbaa6706e92f3fc0bc97a8d341edf607adb88ac000000000000000000000000000000000000000400008085202f8901077fd56d65177fae5cf4263de4dd934bb9bb088f9ff42c2ba5d910976c15a06a010000006b483045022100d48c14bd9d024b74219ee592c72920f65a3909f06dc6e9bd15d1da90a15ec7c402204a0711a97120224208a2ac1a6c73f62198a0bc4b4dfdd3bf21cc386562df97270121027447a7184ab49f484de98c58ab7907bd12f16ceb3a086e61008632bbc309562bffffffff0280f8a932000000001976a91477af1ed0aef2a4b26c833ecabf8f20011271957888ac2eddca15000000001976a9142fe27b53a8c65b3563d3659f987540b8e9dce8a388ac000000000000000000000000000000000000000400008085202f890138e37605d90d8a1c567ba1e2beb36013caa507d6a431de698677717caa791252010000006b48304502210093d6881cdacfbe18a01c0f30982787bca7c6ba8719873212dcf2d4329956085702204233e0e265ff258f4b34556821bc23c6b408907c4249334aedafa1fa9bc94625012102a29793f1f9cee06a600b3e02a740aaeacfc1b666bd1bb1c1e9ba02f4e6fb2e6bffffffff028066ab13000000001976a9147293b82abc5cc994a5380ebea8fe933ad0dc4ec188ac9e4f1f02000000001976a914fe2f2738ed40c7d437a3bd4400d4e6fa5df9657788ac000000000000000000000000000000000000000400008085202f89017942b3fb048a1e73e90c37d7347eb35d37f0a19b678494c75971002700cd161d000000006b4830450221009b13e55e73334188c2b09bb079068c09cc1d763fe77da1956e5acb60e0321da802205dfd2f7e6599716b8fe34e00a2ef47fdca875ac6a8ff9b564205ce169113bf500121038b9a767c2eb28bf50f740ff8a5a2ce8a98f06a8f304a022a1d1da72a0caae621ffffffffbedb271300000000001976a9142fc1e89bfe0725ad4879387e0991b5a86414cb5b88acf2c90f00000000001976a9143293f122daf2baf9b75d4e46d48802f945ad3c2188acf4840f00000000001976a91450fc643c358d5031cd24093548062ca58310111288ac70e93200000000001976a91464f9f503fd5d2bca70c347ab4ab5a2c0b0dca88588ac4f011100000000001976a9147ef2e8b5a26220b4cb414ad55d41dc411634c28788acbf291400000000001976a91496d369cded2bdac7edb6ad9980c1d4e80a0319cb88ac55121300000000001976a914b3a297905c079941d33ceac9109dac2dabb3493688acf0710f00000000001976a914c8f1c418216494ab67d8efb9a9e466453d1c673388acf13c0100000000001976a9147a868ab629a4cc8a06f27c127e78f3da1e9f17df88ac04311000000000001976a9147f231f473813d228c4a1387d74d4addf81f6ced988ac13289900000000001976a914a9639e3537d64c0602b85c797bd3f411dc85a36188ace9950f00000000001976a9144a2669602019e49a2e3e86969acc27421f42805c88acff941e00000000001976a91461b2bfd825f59a5cfabf710971d977ec6ed0498288acae1a1100000000001976a9145a267ba827476c6aa73293c511fa0a1bd488010688acde510d06000000001976a91463314c74a438dd78620a346f6fd71e648017851288ac79141400000000001976a9146be4f6f28a56ee3f9d3214714749fb9590eb83f988ac77031400000000001976a914a16dce989a9bfe693d5fe5e658eb150f32a7dc5f88ac0c401000000000001976a914b18d919a90f71466e0d6e9acd615923f6d1d89e388ac37450f00000000001976a91438900b5a3eff94d1578c79c4608f29e2959144a188ac167f1100000000001976a9142b14cdcf533e46132826e160ec91bcef32268fcc88aceb9d0f00000000001976a914656458ea0756811fdc180511c5984e6e82773f2188acb8601000000000001976a91479ec46a5d1e1396e1032432b976a91eb97020c9088acab480f00000000001976a914810cf1390260a3592aacf161b0c8c469d0b06ce288acc3d31100000000001976a91481aec48be53e00d7b7255b079eb4025822784e8e88ac318a1600000000001976a914a5d07355463b28d99ada5b4dcaf8f64fe49859f388ac383d1400000000001976a91407136bf193c12f1d588f2d13dcb84f1b5fee3df688ac03eee600000000001976a91428cb491ca091f81887dcf2519e0ed84635c6372b88acd1ab1e00000000001976a914a9782a584de62c08255a869d63aadf256ca3275d88ac14720f00000000001976a914e2c61fc9a3846ac5c1894c59c5a287f4c8c7d9bf88ac09681500000000001976a91474b1a156f5b7570514e246d367ae1f30f3c0241b88accad90f00000000001976a914c64d1432d11dbf81dea355ca3a554fd2c31137bf88ac961e4d00000000001976a914d9b3dfe3da64d0f3ec79a2a742c30cdd4252cb7b88ac747f1500000000001976a91425c243f0a58b2fde302d55b0372881b221c183ef88ac8f461500000000001976a9143523831934f264221812be99769c2617d935b41288ac85440f00000000001976a9144047ed2b1c04ec89c81b8e490531b748724903e488ac62470f00000000001976a91480abb472db15c957095f70f9db57006a4777711188aca0b99800000000001976a9149225b5435e36fdd79306474cc5efaffee9b4085b88ac915b0f00000000001976a914c10a6f5a8e8e4b9464c3818f4935da18fad08cdb88aceebe1400000000001976a914e8bc90f4875134b5bd6cc36ad098fc02a86fe89088ace1671100000000001976a914e4fcbc5cf718baefb8302f85928eb652c294b25288ac711f1300000000001976a9142e9ce814270861c79d25766cb9861b1eccfa4b6b88ac12650f00000000001976a91465db45b5fc934b6efe4c683a42d42b3a1abdba2a88ac85e80f00000000001976a914a69d4a9df38b072236848a7bd2b0f2ffee9b7c5e88aca84d0f00000000001976a914b7fc076ece98f74fbe26d06f6eb92eb53988334788ac2df80f00000000001976a914e39fe2179e3d2e008470d6d414cb156313e60a7b88ac67870f00000000001976a91417d5e2abe60d6b1a818c08d84482a226a4438ef388ac89061200000000001976a9141d78e981386c351bacbb3c36cb40c29e874fa19e88ac56d72d00000000001976a9145c5c1a1c58a1ee93280d2c9a3574098da98426e588ac9d841000000000001976a914b4a98cfc3881a7fa80d0c523015abb57ef4c970188ac903e2600000000001976a914dad95d6c00ca3e49a490520badf37e43e5cffc6488ac78111100000000001976a914279bdeabb723b4170ab8d514758f6273c7f8303e88ac625d8f00000000001976a91438d411a1b9a61b8aaf94f383fc21fd6460c9bbc188ac95872b00000000001976a914a9689485a7070f922f5d5595328224a61c4dc03488acfb750f000000000017a914e85a97e9afab0335be4420e2494461f2613e0fba8775981500000000001976a914b420dec5107134816bf38cde1b9d3c0c69a2f06a88ac02111100000000001976a914248053ca51c85e5eb02e8903ae6cfdafbbc7bd5f88ac58bd1000000000001976a914139bf6a5462e28098fba88207dd370025138ef1788ac3caf1300000000001976a9143539c7f6e1ea045f306537819d78ad991d16816b88ac3a5d0f00000000001976a91470c47752de9794107d5398e51ddf6bbd891b566d88aca7481100000000001976a9147ba992181fc09513ae0a423d6f6f85afb762bbb488ac74011400000000001976a91487312841b7f30180d3b0baa40400c3eaeb84bace88ac12011400000000001976a914b35b7352fe46305d06762e3c62da3965844c9e2788ac02a60f00000000001976a914d9db616f7ca7456b7ff605257d8177769a3d9d5588ac25551000000000001976a9149411fe96e90926ebde67f292f41629b54960677688acd2392300000000001976a914a5ca26b5970ebf5d0bc1d7de2d1629c8a71cd75588acd2984d00000000001976a9141afcbb1155d4b22293fd188faeb94c531fe6cf8588ace2691000000000001976a91491453b1b95ee722fd4e9ea6a903a05f04809206d88acc9b42100000000001976a9140656f0d7cad8cdb3c387f037ae283958dd7b7d6588acbebf4c00000000001976a914079a22f6f0f76af49ec36b0e1cdd25490918dc6c88acad981200000000001976a9143c3ee9629c853ac3b7e14143f4bb3fd9c2ad89d788ac1fa21000000000001976a9148697db8f3d23af4eea5be02b05e18f1b3ac5e0b788ac7c041000000000001976a914fcae54913f9ba427f12d3af34204f1ea2657422688acda4c0f00000000001976a914fd44f6273ec3740bfb7816ce4a1f710d4c1c269a88acc3ef2000000000001976a914f8efe6ac4d540683494a15b29cc25938ee6a419c88ac60c90400000000001976a9141864c0a5f3529aa4ec8e51bc9ddc22ce4b4e157588acd3f81200000000001976a914286aa9d5367941592c587cc9f12f6f2d01b9c49188acb4831000000000001976a9145ec7f2d857f1afd9124632a124b858c243824e0688ac2afe1000000000001976a914c6f6cb74ac77b327191b4751739871db3c31145488ac1cb30f00000000001976a914cf4f53cd8154f7de610666481cf371e54a5edab288ac9f480f00000000001976a9141551dbcd39928508eff7f39afbefa91f9ad926db88acf0801f00000000001976a91421239cd7c315f5005496cc3c53636d760c67fd2588acc64b0f00000000001976a914e7e90f75a8662b3fcdc655a12e399f54acba96c188ac7c441000000000001976a914ff4ac4ec519780c8bf9ee8ab28a1f5ac53dcbe2688acdba70f00000000001976a914439cc08d45784b51e38fc12ec9ca85f9d02bac3588ac50b21700000000001976a914a0054b86fd678eb5719fd2bac37718f7bca12f1e88aca9420f00000000001976a914e311db3b077e9436a25a97203a29e9a20423be2688ac254a1100000000001976a914e1d015d15169a3bf15c3a9492b4ec9a8355146ec88ac3aed4f00000000001976a914d030e8b5034508cc7f961b3eb9e13899b81139af88ac77580f00000000001976a914db658934bc6a44688f502e4fe9835b4414f7107b88ac57b7cb01000000001976a914e39250cc294b3be3d198e7817c9867254a589ec388ac9e0e1000000000001976a914f52220601aae51f5e6db37eefc7520d4af44435b88ac4e510f00000000001976a9141ac3eddcbafb2099a966dbffba2417d8b36fc1ce88ac5ded0f00000000001976a9145c3d7e8e327ca280b1c97988ffb1129449516d3b88acc7d91300000000001976a914b28517de1dfe045f269e52706a4b405b24856e3a88ac58841100000000001976a914bec87f89bf7d3b559f5b28a5673e37338661a11d88ac22251000000000001976a9147d193f74ce7e78ca3c38a4c8b9eda2257b60d4ff88acf9750f00000000001976a91489be62b64973ac3bdeb5b6f9f0873891793f570288acda3aa000000000001976a914659e40a17b0888d457f92b4b923ac2d867e997db88ac31d90f00000000001976a9147427a849f936ee264c131ea97e7da94066f94af088acb5201000000000001976a914f9e28dbb4ba9cee3bcad81b4703dc4740c8094c988ac55611600000000001976a914feb639f6adcc177617ea86fab17fa1c8fa09015e88ac19111100000000001976a91411084657ab9aa3d311561ab532b5db488ad8772488ac2d459900000000001976a914188bfafc2a5a67e6e79ec11438db612fc825070988ac14301000000000001976a914753a1448db0479d3b29490eea4a4ef02931858b088acd7051100000000001976a914823c58f257798e1f4ec4a99d3e6862af85860a7c88aca6ae0f00000000001976a914d52abe8429a6955afe9ebb224e0527480b974e8c88ac23ae0f00000000001976a914f241928fc454540b7e0a258ff2be7f085cdecc9388ac68121100000000001976a9148f21b0d7fdff914d52bccd4a58a4a7b75d551e6f88ac485b0f00000000001976a9142adbb7e041d14b8838d81653f8a57d08df4d1b9588ac48441101000000001976a914602606d441b263883a98ac7396700acc789541cd88acff8a0f00000000001976a914692a05e4e7e8b648f907ae860d45363152c432b888ace9c61000000000001976a91478c5a1f419b6aa2b247462f2bddf3139492605c888ac02ed1300000000001976a9147a0c64f98187cdff7a0844d3e088f42424cbc33588ac53810f00000000001976a9149d824bdca3ccfba6b2ae09d9e9e392f456440dd488ac8a7a0f00000000001976a914d0fa032a59dc1d94244353d72b1d2b22bec99b0488acb45a0f00000000001976a914dedf21cfbbd6f546d82c33f8bd29bac97854a61188ac84331e00000000001976a914acbddc1ad4d7f6b9484226a76f55dacb6467464088acb3951600000000001976a914040cbe8adb0d386dcf2814288e2ee232f347b36b88acd96f1100000000001976a91416f54e41ac7e0572500eb38078cea0fb54c7ec0888ac10980f00000000001976a914cc1d20c43acbbe2e117a9a8c3a81d03784d0677d88ac60841600000000001976a914cc3c84aedfbb5580e73785ec9a447224ba8da3f988ac5bd91f00000000001976a914347239845637a4ba24c8e8a92d9d1bda6472a3c788acb0bb1000000000001976a9146d034fcc469c361eb7f325318c4f3f02c59db5a988accbab1300000000001976a9146d134c6009a87d629149ac18f708fc15459d717888ac6a371100000000001976a9149ee0df84191ab83f55f68836c3115eb40d0d4ef488acbe622000000000001976a914c427307199f741f0f718f8468d6c2ef29cfc861088ac95ca1100000000001976a9142a5601532e379b1c327c8f250ef5cd0e90c9bcf388ac41311100000000001976a914836f6217a7c3e1d3a4428060041cded94d812e5b88acec63a300000000001976a914ab0dc2ca76932a5d810ec9f67c38aacf31aeeeb988aca8b61100000000001976a9147d24fdf26cea37168f143f73d1d941a6ca7b37ae88ac95911400000000001976a91481efeedd8c4171eb575633143991253a1f01ecb488ac76a30f00000000001976a9145733e14e3aff4f9cb82c63d7a48133c5ef25a13a88ac3a6b2f00000000001976a91477e0cd572d6e09709ab1269d71120165398faee488ac16460f00000000001976a9147381b2b673a016df5875bc810e9110c0ce4aa8ff88ac45591300000000001976a914d5536f34987ed1a691d4351110e6039224535b0788acd3212100000000001976a914e29c11748114a121bb9e1748a9180abb72c3e96988ac09c73501000000001976a914e6766b39306450cf922eb139a63afbafd565adca88ac56451000000000001976a914efd0c55e8ac56abd7da087f45cac46d26e24379688acc3011500000000001976a91428fc598ecef1b343f3b0131faf864291e23a5f5688acffad1400000000001976a914440b60242fa983ba5a83a35bb09581bbd9a644ab88ac072c1800000000001976a9145ef848cfd5a888fe5c5999e133c6fb27584fab6b88aca0744301000000001976a9148a5a8410d00aeb4dbafa2b5ffc13c72b7da1277088acd0d17800000000001976a914c9e6ab854cd3bff4c42d92ff3b98a2be42b1e59588aca3478100000000001976a91412fda64e5551a560a8536bc62d8146a12debfd2c88ac6d660f00000000001976a9141222c6b463f6844cacdabcd3185f689587ca337b88ac5a421100000000001976a9144bbfac3fb6e1f2c0f60adb7aa8342cce67184d0688ac20481000000000001976a91472a28214eb64298a92357de5a18178259097c73a88acf76b0f00000000001976a914970770c1c61c717b622edfda36a38d717105f9b488acd1d71100000000001976a91492c259d951597c3921642cde546c4fee83cab5f688acb3192c00000000001976a914b6a07e6302e8eba1cf1d2f8d1cabcd62c3ed99c588ac309b0f00000000001976a914e1238e80122a94f1bae3f2bbdaa719e4c6e69a9e88acffcf1000000000001976a9142e1fe9946c2d2a0ab73ad155790fb1c8d444aa5988acb5c9fb02000000001976a9143a2c03adb92becd5374ce338e841627aeb13642888ac8e771000000000001976a91443a93e19e7b508596451097933a4f6cae352a7a588acbd3d1300000000001976a9144b2a41a411a053930d7080331949b84878a6913088acc7471400000000001976a914a8a8fc2361c0b5e197cc4b4b9976c2f38943be3b88ac6ee810000000000017a914d1347e5f703a42eb5aa776ae6d8fe8dfeb54c6a38732bb1500000000001976a914d380da2823e7721d8f4ba12817bed0324c29c64e88ac20460f00000000001976a9140a2716c74cc42c314a04216c212658815a0b96cb88acb6a60f00000000001976a9141fda7c9387198cf19e39354f5d1bd1664507ad4a88ac7f8d1300000000001976a914247b512c0fc9633cf0faeeb2b04b7813dede4cf688acf64f0f00000000001976a9142b3536a43c18799e4821eef23a29b5d013ae2b6788ace1d70f00000000001976a9149c4177f410a28b9e1f6cfb798b699300f621cc0f88acfe830f00000000001976a914b131c258f1a1fcec4ccaced0cedd85e4032f2a4f88ac71480f00000000001976a914130ffb5bda2a9cddbc21e88de9abf05da2456b0f88ac24520f00000000001976a9144bffb24e4f7a8e03f1290adf7c670ad914da145488ac0c211000000000001976a9147f9c457f7d6f1cf534bac363602dd64a05cdc2a588aca0171000000000001976a914fae4ed560e3ab1c770aadc30dba9692c199bc2a188ac145f4c00000000001976a9142b497a4327e2db897eb8976c710cfcc55e58db3b88ac21540f00000000001976a9144b77d779ab402f852aa976d4360c21d5a26ca9ec88ac74a11e00000000001976a9148177e0a5ad88f1d10d7a3e74aeaaea890169602a88ac7ee31300000000001976a914827fa756eaf9d64388b9f4264c91fb6903aa5c4588acfbf70f00000000001976a914b4c7bc14e00f73af61aecce2dc583168c31c4b9d88ac0d820f00000000001976a91410d28402d5bd0160fe4d5eb40a9c3568a5d42fe188ac75c80f00000000001976a9144af63196a28bff87a9ca0155f538cc244fbbcdf888ac88af1c00000000001976a9149f0b4cfd64e900906ac67d6753da91a9a504562a88ac2bb01f00000000001976a914c6733fb8a1caa92ed3aadf3f83f878ecb5d56e9988ac1efb1000000000001976a91442cb831fda7fc20201ad85b9ab82bb8b367863d388ac84b70f00000000001976a9144d011ca4b5c575d9065da51a54b59eba5c4f5d9888accbd40f00000000001976a9147b77ca275144d150f1b9f0ffe08f6c63abd315ca88ac81b10f00000000001976a9148979925d61f9a9dbdf85ff5130e7dfc55f3a4dc488ac93520f00000000001976a914f01ec5c5b81cf2ebffc576fa374a56e0bd29d49388acb2e20100000000001976a91444e4b9f602c81fa9ff7bfe7020cd2210717d36ce88ac921c1200000000001976a9146d577cd0a7ee95ee98eced1838ac141c0fd06db088ac0cce9800000000001976a91477dd8c6ebeb2cc5a7f193bb3ac1817ad4c6011f988ac6c610f00000000001976a91481af8c00f9d052fd4ce7cb5d2638b86ff1f2787788ace0ad6302000000001976a9149534939288c542fe80c2cfa3ae4feb36aea5db9f88acaa790f00000000001976a914c885a86642001305a8f69a2df4064b56fe5baf0b88ac95a50f00000000001976a914e989fb3c4e488bc83fe3e10b1439eecb2670698e88acb4f0dddf050000001976a914e2b7aa42a291a23908161c9071a3dad51d02e10888ac00000000cda2060000000000000000000000000400008085202f8903c88f79329b0c4eae2777582d304c0e976d0febebc116bf8b35d5c8ce5cb5cd324c0000006b483045022100d17d5dc13d1eff9358e53cf3b74bc6550b2fcd1b4d5dc50fc143f19d11098a5d02206990e0b009814b5d5b14e2923406cdaf6950e766302eb61b7047e7671fd2a21a01210317ad10576b806c1824c46e5517e979e7a161b76315ba93e6fca5a3b4bf66f5e4feffffff6c2877d3879245810ebb32a2664a708677e20b30e1e5be5516c5e024af968f96020000006b483045022100e91f329f1dfa5e777c3db5204b05916c48e049213a11084356b66033a7557c7a02207adc7ddfc736be69840274f1ec94e3657614a2683a0a832a06b11bcff4893196012103d8c7454c1b13457d66980610122fc84e2ca876c251f65b4f94211e75955080d9feffffff59152d5ad96891a193920e241bad45efdbe153d7c5b0d4652526af5405b3de37000000006a47304402204fa72cabb5ceff3b3da9ebe1127c441b9840acd4b8c7e5a3599d8f28687d659a02206506df0f7ac1e0d331cb66edec89c92fce4d129234784bf0c007a5a5d526b879012103a633a7efb4b409a7e2135ae87a2a800450b9d91f1f28d69072b273f318e611bffeffffff03de3812000000000017a91439dec991976767ded3f51515033201049401710d8733231a00000000001976a914c743b8321f3116a169069aaf9f05d091ec6afe4b88ac809a10000000000017a91430b3cce69378a7c661368c669e135f951f3e63d987aea20600cda206000000000000000000000000") .expect("Block bytes are in valid hex representation"); + pub static ref DUMMY_TX1 : Vec = >::from_hex("01000000019921d81f33e0c8b53a23d2e60643807bfe00e59fbb5f3d3e6fba20e73c2049a00000000000ffffffff0140420f00000000001976a914588cff9d4339d754758ade214b3edc69ce57b7f588ac00000000").expect("Block bytes are in valid hex representation"); + pub static ref DUMMY_INPUT1 : Vec = >::from_hex("1d322261f61dd7093b1880b735152cf0ed19beabee374046e69559c9fb8858bba0000000000ffffffff0").expect("Input bytes are in valid hex representation"); + pub static ref DUMMY_OUTPUT1 : Vec = >::from_hex("0140420f00000000001976a914588cff9d4339d754758ade214b3edc69ce57b7f588ac").expect("Output bytes are in valid hex representation"); // https://github.com/zcash/zips/blob/master/zip-0143.rst#test-vector-1 pub static ref ZIP143_1 : Vec = >::from_hex("030000807082c4030002e7719811893e0000095200ac6551ac636565b2835a0805750200025151481cdd86b3cc431800").expect("Transaction bytes are in valid hex representation"); // https://github.com/zcash/zips/blob/master/zip-0143.rst#test-vector-2 @@ -248,5 +251,4 @@ lazy_static! { pub static ref ZIP243_2 : Vec = >::from_hex("0400008085202f89020bbe32a598c22adfb48cef72ba5d4287c0cefbacfd8ce195b4963c34a94bba7a175dae4b0465ac656353708915090f47a068e227433f9e49d3aa09e356d8d66d0c0121e91a3c4aa3f27fa1b63396e2b41d090063535300ac53ac514e97056802da071b970d4807000152a844550bdc2002000752526a65520052d7034302011b9a076620edc067ff0200000353e3b8a71face1c9f37745ed36883529304bfd5a390b37bc5a3445241f03f64a818820dfeddd75375159fbd21eca9872104f8d7b3c8c869703a1e7848a5c941e45a9c7943446d0dc9627cb31f80e7aa596d4821dc99a7d777cd57e194842a023471f0f6288a150647b2afe9df7cccf01f5cde5f04680bbfed87f6cf429fb27ad6babe791766611cf5bc20e48bef119259b9b8a0e39c3df28cb9582ea338601cdc481b32fb82adeebb3dade25d1a3df20c37e712506b5d996c49a9f0f30ddcb91fe9004e1e83294a6c9203d94e8dc2cbb449de4155032604e47997016b304fd437d8235045e255a19b743a0a9f2e336b44cae307bb3987bd3e4e777fbb34c0ab8cc3d67466c0a88dd4ccad18a07a8d1068df5b629e5718d0f6df5c957cf71bb00a5178f175caca944e635c5159f738e2402a2d21aa081e10e456afb00b9f62416c8b9c0f7228f510729e0be3f305313d77f7379dc2af24869c6c74ee4471498861d192f0ff0f508285dab6b6a36ccf7d12256cc76b95503720ac672d08268d2cf7773b6ba2a5f664847bf707f2fc10c98f2f006ec22ccb5a8c8b7c40c7c2d49a6639b9f2ce33c25c04bc461e744dfa536b00d94baddf4f4d14044c695a33881477df124f0fcf206a9fb2e65e304cdbf0c4d2390170c130ab849c2f22b5cdd3921640c8cf1976ae1010b0dfd9cb2543e45f99749cc4d61f2e8aabfe98bd905fa39951b33ea769c45ab9531c57209862ad12fd76ba4807e65417b6cd12fa8ec916f013ebb8706a96effeda06c4be24b04846392e9d1e6930eae01fa21fbd700583fb598b92c8f4eb8a61aa6235db60f2841cf3a1c6ab54c67066844711d091eb931a1bd6281aedf2a0e8fab18817202a9be06402ed9cc720c16bfe881e4df4255e87afb7fc62f38116bbe03cd8a3cb11a27d568414782f47b1a44c97c680467694bc9709d32916c97e8006cbb07ba0e4180a3738038c374c4cce8f32959afb25f303f5815c4533124acf9d18940e77522ac5dc4b9570aae8f47b7f57fd8767bea1a24ae7bed65b4afdc8f1278c30e2db98fd172730ac6bbed4f1127cd32b04a95b205526cfcb4c4e1cc955175b3e8de1f5d81b18669692350aaa1a1d797617582e54d7a5b57a683b32fb1098062dad7b0c2eb518f6862e83db25e3dbaf7aed504de932acb99d735992ce62bae9ef893ff6acc0ffcf8e3483e146b9d49dd8c7835f43a37dca0787e3ec9f6605223d5ba7ae0ab9025b73bc03f7fac36c009a56d4d95d1e81d3b3ebca7e54cc1a12d127b57c8138976e791013b015f06a624f521b6ee04ec980893c7e5e01a336203594094f82833d74427880084d35863c8e7ebb5c9eed98e72572ec40c79b26623b58022f489b0893d88be63f3f8c0d23249ebcde13db9312941c36c1d1cbcabac0c78cb3b1912db0dcbfe1893d9b51be4af1d000bac1ad0a3ae2ce1e73225fb114d05af4cefc06e875f074ffeae0cba7da3a516c173be1c513323e119f635e8209a074b216b7023fadc2d25949c90037e71e3e550726d210a2c688342e52440635e9cc14afe10102621a9c9accb782e9e4a5fa87f0a956f5b85509960285c22627c59483a5a4c28cce4b156e551406a7ee8355656a21e43e38ce129fdadb759eddfa08f00fc8e567cef93c6792d01df05e6d580f4d5d48df042451a33590d3e8cf49b2627218f0c292fa66ada945fa55bb23548e33a83a562957a3149a993cc472362298736a8b778d97ce423013d64b32cd172efa551bf7f368f04bdaec6091a3004a757598b801dcf675cb83e43a53ae8b254d333bcda20d4817d3477abfba25bb83df5949c126f149b1d99341e4e6f9120f4d41e629185002c72c012c414d2382a6d47c7b3deaba770c400ca96b2814f6b26c3ef17429f1a98c85d83db20efad48be8996fb1bff591efff360fe1199056c56e5feec61a7b8b9f699d6012c2849232f329fef95c7af370098ffe4918e0ca1df47f275867b739e0a514d3209325e217045927b479c1ce2e5d54f25488cad1513e3f44a21266cfd841633327dee6cf810fbf7393e317d9e53d1be1d5ae7839b66b943b9ed18f2c530e975422332c3439cce49a29f2a336a4851263c5e9bd13d731109e844b7f8c392a5c1dcaa2ae5f50ff63fab9765e016702c35a67cd7364d3fab552fb349e35c15c50250453fd18f7b855992632e2c76c0fbf1ef963ea80e3223de3277bc559251725829ec03f213ba8955cab2822ff21a9b0a4904d668fcd77224bde3dd01f6ffc4828f6b64230b35c6a049873494276ea1d7ed5e92cb4f90ba83a9e49601b194042f2900d99d312d7b70508cf176066d154dbe96ef9d4367e4c840e4a17b5e5122e8ebe2158a3c5f4cbae21ea3fa1ae6c25a9462ebcbb0fd5f14554bc97747c33e34da90c816d8d0d50bfe37618c5812891484fa259322c15092d4155d8696d6f12f24fd364496b3be0871ca3dd9625348a614b59bde45885649bae36de34def8fcec85343475d976ae1e9b27829ce2ac5efd0b399a8b448be6504294ee6b3c1c6a5342d7c01ae9d8ad3070c2b1a91573af5e0c5e4cbbf4acdc6b54c9272200d9970250c17c1036f06085c41858ed3a0c48150bc697e4a695fef335f7ad07e1a46dc767ff822db70e6669080b9816b2232c81a4c66cc586abfe1eaa8ca6cf41fc30eb8dc57c37a3c39c59c94232df9d388dbfa35c2cd5c75f328e9fea78f65568f2bb934c82c4142da69d12ca7de9a7df706400ec79878d868e17e8f71ea31495a8bae7bdc2e48b5118771c2fca078cca1fce0d7ef0af3478cf36f69e85a41dd29b4294a65d3e055ff718dd9dc8c75e7e5b2efe442637371b7c48f6ee99e3ea38a4b0f2f67fc2b908cda657eae754e037e262e9a9f9bd7ec4267ed8e96930e1084783c37d6f9dd15fd29f4cc477e66f130d630430dcc0104899b4f9f46eb090ef7fc90b479abf61f93955ee00e6a1848f1ab14ad334f2b68035808cdf1bb9e9d9a816baf728a955b960b7701fa626687dc3c9cba646337b53e29816e9482ddf5578a8768aae477fce410ac2d5de6095861c111d7feb3e6bb4fbb5a54955495972798350a253f05f66c2ecfcbc0ed43f5ec2e6d8dba15a51254d97b1821107c07dd9a16ef8406f943e282b95d4b362530c913d6ba421df6027de5af1e4745d5868106954be6c1962780a2941072e95131b1679df0637625042c37d48ffb152e5ebc185c8a2b7d4385f1c95af937df78dfd8757fab434968b0b57c66574468f160b447ac8221e5060676a842a1c6b7172dd3340f764070ab1fe091c5c74c95a5dc043390723a4c127da14cdde1dc2675a62340b3e6afd0522a31de26e7d1ec3a9c8a091ffdc75b7ecfdc7c12995a5e37ce3488bd29f8629d68f696492448dd526697476dc061346ebe3f677217ff9c60efce943af28dfd3f9e59692598a6047c23c4c01400f1ab5730eac0ae8d5843d5051c376240172af218d7a1ecfe65b4f75100638983c14de4974755dade8018c9b8f4543fb095961513e67c61dbc59c607f9b51f8d09bdcad28bcfb9e5d2744ea8848b2623ac07f8ef61a81a35910b8a1baf39a919a7b60bc604d63185f759221d847cc54a22765a4c33475b5791e9af3271fc8d9350667090d8184ec50522d804f23c4fb44ffa481bc92ae408d1b9f2b131904f9705c59e2f4bde7a3b2c085d93fd2abc5e14d163001a12f51938d021afa92239b873dc6c357eaa8af4ee6d00540657fe32914103b5d98f68bd3e2b5359f08ccd88d0c811e4c31fbb49f3a90bbd05dce62f344e7077593159ae35050b04c9e6b86bc432dc8b048c73c0018ca5b69411297732a4e1aa99a928c71e7a24fd277856aa42501e51b012aea9446a2104e93f815a0b3a29b458314f3d8be2b9823d342f46213e942a7e19a46e970b5c506708430317b1bb3b35df68ae33a4926a03e6bfeb5510416fcbb0524c9ca5074156cc5a5d6fe1c995edc60a2f550411aa41e3da3bdcf64bcf04a0510571b936d47e55cec0330008dfe73563404f047d7f3a8a3d7743bc554955210f1eb0d08599ea77d5f974d87176d37d98b9c0ad440407209ed6a9f08464d565593e1a63b938536b49244e97d").expect("Transaction bytes are in valid hex representation"); // https://github.com/zcash/zips/blob/master/zip-0243.rst#test-vector-3 pub static ref ZIP243_3 : Vec = >::from_hex("0400008085202f8901a8c685478265f4c14dada651969c45a65e1aeb8cd6791f2f5bb6a1d9952104d9010000006b483045022100a61e5d557568c2ddc1d9b03a7173c6ce7c996c4daecab007ac8f34bee01e6b9702204d38fdc0bcf2728a69fde78462a10fb45a9baa27873e6a5fc45fb5c76764202a01210365ffea3efa3908918a8b8627724af852fc9b86d7375b103ab0543cf418bcaa7ffeffffff02005a6202000000001976a9148132712c3ff19f3a151234616777420a6d7ef22688ac8b959800000000001976a9145453e4698f02a38abdaa521cd1ff2dee6fac187188ac29b0040048b004000000000000000000000000").expect("Transaction bytes are in valid hex representation"); - }