132 lines
3.8 KiB
Rust
132 lines
3.8 KiB
Rust
//! Generate blockchain testing constructions
|
|
use chrono::{DateTime, NaiveDateTime, Utc};
|
|
use std::sync::Arc;
|
|
|
|
use crate::{
|
|
serialization::{ZcashDeserialize, ZcashSerialize},
|
|
transaction::{LockTime, Transaction, TransparentInput, TransparentOutput},
|
|
};
|
|
|
|
use super::super::{serialize::MAX_BLOCK_BYTES, Block, Header};
|
|
|
|
/// Generate a block header
|
|
pub fn block_header() -> Header {
|
|
Header::zcash_deserialize(&zebra_test::vectors::DUMMY_HEADER[..]).unwrap()
|
|
}
|
|
|
|
/// 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 header = block_header();
|
|
|
|
// Serialize header
|
|
let mut data_header = Vec::new();
|
|
header
|
|
.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 += 1;
|
|
}
|
|
|
|
// Create transactions to be just below or just above the limit
|
|
let transactions = std::iter::repeat(Arc::new(tx))
|
|
.take(max_transactions_in_block)
|
|
.collect::<Vec<_>>();
|
|
|
|
// Add the transactions into a block
|
|
Block {
|
|
header,
|
|
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 header = block_header();
|
|
|
|
// Serialize header
|
|
let mut data_header = Vec::new();
|
|
header
|
|
.zcash_serialize(&mut data_header)
|
|
.expect("Block header should serialize");
|
|
|
|
// Serialize a LockTime
|
|
let lock_time = LockTime::Time(DateTime::<Utc>::from_utc(
|
|
NaiveDateTime::from_timestamp(61, 0),
|
|
Utc,
|
|
));
|
|
let mut data_locktime = Vec::new();
|
|
lock_time
|
|
.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 += 1;
|
|
}
|
|
|
|
let mut outputs = Vec::new();
|
|
|
|
// Create inputs to be just below the limit
|
|
let inputs = std::iter::repeat(input)
|
|
.take(max_inputs_in_tx)
|
|
.collect::<Vec<_>>();
|
|
|
|
// 1 single output
|
|
outputs.push(output);
|
|
|
|
// Create a big transaction
|
|
let big_transaction = Transaction::V1 {
|
|
inputs,
|
|
outputs,
|
|
lock_time,
|
|
};
|
|
|
|
// Put the big transaction into a block
|
|
let transactions = vec![Arc::new(big_transaction)];
|
|
Block {
|
|
header,
|
|
transactions,
|
|
}
|
|
}
|