zebra_chain/block/tests/
generate.rs1use chrono::DateTime;
4use std::sync::Arc;
5
6use crate::{
7 block::{serialize::MAX_BLOCK_BYTES, Block, Header},
8 serialization::{ZcashDeserialize, ZcashSerialize},
9 transaction::{LockTime, Transaction},
10 transparent,
11};
12
13pub const MIN_LARGE_BLOCK_BYTES: u64 = MAX_BLOCK_BYTES - 100;
15
16pub const MAX_COMPACT_SIZE_BYTES: usize = 4;
19
20pub const TX_V1_HEADER_BYTES: usize = 4;
22
23pub fn block_header() -> (Header, Vec<u8>) {
25 let block_header = Header::zcash_deserialize(&zebra_test::vectors::DUMMY_HEADER[..]).unwrap();
29 let block_header_bytes = block_header.zcash_serialize_to_vec().unwrap();
30
31 (block_header, block_header_bytes)
32}
33
34pub fn transaction() -> (Transaction, Vec<u8>) {
36 let transaction = Transaction::zcash_deserialize(&zebra_test::vectors::DUMMY_TX1[..]).unwrap();
40 let transaction_bytes = transaction.zcash_serialize_to_vec().unwrap();
41
42 (transaction, transaction_bytes)
43}
44
45pub fn input() -> (transparent::Input, Vec<u8>) {
47 let input =
51 transparent::Input::zcash_deserialize(&zebra_test::vectors::DUMMY_INPUT1[..]).unwrap();
52 let input_bytes = input.zcash_serialize_to_vec().unwrap();
53
54 (input, input_bytes)
55}
56
57pub fn output() -> (transparent::Output, Vec<u8>) {
59 let output =
63 transparent::Output::zcash_deserialize(&zebra_test::vectors::DUMMY_OUTPUT1[..]).unwrap();
64 let output_bytes = output.zcash_serialize_to_vec().unwrap();
65
66 (output, output_bytes)
67}
68
69pub fn large_multi_transaction_block() -> Block {
73 multi_transaction_block(false)
74}
75
76pub fn large_single_transaction_block_many_inputs() -> Block {
81 single_transaction_block_many_inputs(false)
82}
83
84pub fn large_single_transaction_block_many_outputs() -> Block {
89 single_transaction_block_many_outputs(false)
90}
91
92pub fn oversized_multi_transaction_block() -> Block {
96 multi_transaction_block(true)
97}
98
99pub fn oversized_single_transaction_block_many_inputs() -> Block {
104 single_transaction_block_many_inputs(true)
105}
106
107pub fn oversized_single_transaction_block_many_outputs() -> Block {
112 single_transaction_block_many_outputs(true)
113}
114
115fn multi_transaction_block(oversized: bool) -> Block {
117 let (transaction, transaction_bytes) = transaction();
119
120 let (block_header, block_header_bytes) = block_header();
122
123 let mut max_transactions_in_block = (usize::try_from(MAX_BLOCK_BYTES).unwrap()
126 - block_header_bytes.len()
127 - MAX_COMPACT_SIZE_BYTES)
128 / transaction_bytes.len();
129 if oversized {
130 max_transactions_in_block += 1;
131 }
132
133 let transactions =
135 std::iter::repeat_n(Arc::new(transaction), max_transactions_in_block).collect::<Vec<_>>();
136
137 let block = Block {
139 header: block_header.into(),
140 transactions,
141 };
142
143 let serialized_len = block.zcash_serialize_to_vec().unwrap().len();
144 assert_eq!(
145 oversized,
146 serialized_len > MAX_BLOCK_BYTES.try_into().unwrap(),
147 "block is over-sized if requested:\n\
148 oversized: {oversized},\n\
149 serialized_len: {serialized_len},\n\
150 MAX_BLOCK_BYTES: {MAX_BLOCK_BYTES},",
151 );
152 assert!(
153 serialized_len > MIN_LARGE_BLOCK_BYTES.try_into().unwrap(),
154 "block is large\n\
155 oversized: {oversized},\n\
156 serialized_len: {serialized_len},\n\
157 MIN_LARGE_BLOCK_BYTES: {MIN_LARGE_BLOCK_BYTES},",
158 );
159
160 block
161}
162
163fn single_transaction_block_many_inputs(oversized: bool) -> Block {
165 let (input, input_bytes) = input();
167 let (output, output_bytes) = output();
168
169 let (block_header, block_header_bytes) = block_header();
171
172 let lock_time = LockTime::Time(DateTime::from_timestamp(61, 0).unwrap());
173 let lock_time_bytes = lock_time.zcash_serialize_to_vec().unwrap();
174
175 let mut max_inputs_in_tx = (usize::try_from(MAX_BLOCK_BYTES).unwrap()
179 - block_header_bytes.len()
180 - 1
181 - TX_V1_HEADER_BYTES
182 - lock_time_bytes.len()
183 - MAX_COMPACT_SIZE_BYTES
184 - 1
185 - output_bytes.len())
186 / input_bytes.len();
187
188 if oversized {
189 max_inputs_in_tx += 1;
190 }
191
192 let mut outputs = Vec::new();
193
194 let inputs = std::iter::repeat_n(input, max_inputs_in_tx).collect::<Vec<_>>();
196
197 outputs.push(output);
199
200 let big_transaction = Transaction::test_v1(inputs, outputs, lock_time);
202
203 let transactions = vec![Arc::new(big_transaction)];
205
206 let block = Block {
207 header: block_header.into(),
208 transactions,
209 };
210
211 let serialized_len = block.zcash_serialize_to_vec().unwrap().len();
212 assert_eq!(
213 oversized,
214 serialized_len > MAX_BLOCK_BYTES.try_into().unwrap(),
215 "block is over-sized if requested:\n\
216 oversized: {oversized},\n\
217 serialized_len: {serialized_len},\n\
218 MAX_BLOCK_BYTES: {MAX_BLOCK_BYTES},",
219 );
220 assert!(
221 serialized_len > MIN_LARGE_BLOCK_BYTES.try_into().unwrap(),
222 "block is large\n\
223 oversized: {oversized},\n\
224 serialized_len: {serialized_len},\n\
225 MIN_LARGE_BLOCK_BYTES: {MIN_LARGE_BLOCK_BYTES},",
226 );
227
228 block
229}
230
231fn single_transaction_block_many_outputs(oversized: bool) -> Block {
233 let (input, input_bytes) = input();
235 let (output, output_bytes) = output();
236
237 let (block_header, block_header_bytes) = block_header();
239
240 let lock_time = LockTime::Time(DateTime::from_timestamp(61, 0).unwrap());
241 let lock_time_bytes = lock_time.zcash_serialize_to_vec().unwrap();
242
243 let mut max_outputs_in_tx = (usize::try_from(MAX_BLOCK_BYTES).unwrap()
247 - block_header_bytes.len()
248 - 1
249 - TX_V1_HEADER_BYTES
250 - lock_time_bytes.len()
251 - 1
252 - input_bytes.len()
253 - MAX_COMPACT_SIZE_BYTES)
254 / output_bytes.len();
255
256 if oversized {
257 max_outputs_in_tx += 1;
258 }
259
260 let inputs = vec![input];
262
263 let outputs = std::iter::repeat_n(output, max_outputs_in_tx).collect::<Vec<_>>();
265
266 let big_transaction = Transaction::test_v1(inputs, outputs, lock_time);
268
269 let transactions = vec![Arc::new(big_transaction)];
271
272 let block = Block {
273 header: block_header.into(),
274 transactions,
275 };
276
277 let serialized_len = block.zcash_serialize_to_vec().unwrap().len();
278 assert_eq!(
279 oversized,
280 serialized_len > MAX_BLOCK_BYTES.try_into().unwrap(),
281 "block is over-sized if requested:\n\
282 oversized: {oversized},\n\
283 serialized_len: {serialized_len},\n\
284 MAX_BLOCK_BYTES: {MAX_BLOCK_BYTES},",
285 );
286 assert!(
287 serialized_len > MIN_LARGE_BLOCK_BYTES.try_into().unwrap(),
288 "block is large\n\
289 oversized: {oversized},\n\
290 serialized_len: {serialized_len},\n\
291 MIN_LARGE_BLOCK_BYTES: {MIN_LARGE_BLOCK_BYTES},",
292 );
293
294 block
295}