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::V1 {
202 inputs,
203 outputs,
204 lock_time,
205 };
206
207 let transactions = vec![Arc::new(big_transaction)];
209
210 let block = Block {
211 header: block_header.into(),
212 transactions,
213 };
214
215 let serialized_len = block.zcash_serialize_to_vec().unwrap().len();
216 assert_eq!(
217 oversized,
218 serialized_len > MAX_BLOCK_BYTES.try_into().unwrap(),
219 "block is over-sized if requested:\n\
220 oversized: {oversized},\n\
221 serialized_len: {serialized_len},\n\
222 MAX_BLOCK_BYTES: {MAX_BLOCK_BYTES},",
223 );
224 assert!(
225 serialized_len > MIN_LARGE_BLOCK_BYTES.try_into().unwrap(),
226 "block is large\n\
227 oversized: {oversized},\n\
228 serialized_len: {serialized_len},\n\
229 MIN_LARGE_BLOCK_BYTES: {MIN_LARGE_BLOCK_BYTES},",
230 );
231
232 block
233}
234
235fn single_transaction_block_many_outputs(oversized: bool) -> Block {
237 let (input, input_bytes) = input();
239 let (output, output_bytes) = output();
240
241 let (block_header, block_header_bytes) = block_header();
243
244 let lock_time = LockTime::Time(DateTime::from_timestamp(61, 0).unwrap());
245 let lock_time_bytes = lock_time.zcash_serialize_to_vec().unwrap();
246
247 let mut max_outputs_in_tx = (usize::try_from(MAX_BLOCK_BYTES).unwrap()
251 - block_header_bytes.len()
252 - 1
253 - TX_V1_HEADER_BYTES
254 - lock_time_bytes.len()
255 - 1
256 - input_bytes.len()
257 - MAX_COMPACT_SIZE_BYTES)
258 / output_bytes.len();
259
260 if oversized {
261 max_outputs_in_tx += 1;
262 }
263
264 let inputs = vec![input];
266
267 let outputs = std::iter::repeat_n(output, max_outputs_in_tx).collect::<Vec<_>>();
269
270 let big_transaction = Transaction::V1 {
272 inputs,
273 outputs,
274 lock_time,
275 };
276
277 let transactions = vec![Arc::new(big_transaction)];
279
280 let block = Block {
281 header: block_header.into(),
282 transactions,
283 };
284
285 let serialized_len = block.zcash_serialize_to_vec().unwrap().len();
286 assert_eq!(
287 oversized,
288 serialized_len > MAX_BLOCK_BYTES.try_into().unwrap(),
289 "block is over-sized if requested:\n\
290 oversized: {oversized},\n\
291 serialized_len: {serialized_len},\n\
292 MAX_BLOCK_BYTES: {MAX_BLOCK_BYTES},",
293 );
294 assert!(
295 serialized_len > MIN_LARGE_BLOCK_BYTES.try_into().unwrap(),
296 "block is large\n\
297 oversized: {oversized},\n\
298 serialized_len: {serialized_len},\n\
299 MIN_LARGE_BLOCK_BYTES: {MIN_LARGE_BLOCK_BYTES},",
300 );
301
302 block
303}