1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
//! Randomised data generation for state data.
use std::sync::Arc;
use zebra_chain::{
amount::Amount,
block::{self, Block},
transaction::Transaction,
transparent,
value_balance::ValueBalance,
};
use crate::{
request::ContextuallyVerifiedBlock, service::chain_tip::ChainTipBlock,
SemanticallyVerifiedBlock,
};
/// Mocks computation done during semantic validation
pub trait Prepare {
/// Runs block semantic validation computation, and returns the result.
/// Test-only method.
fn prepare(self) -> SemanticallyVerifiedBlock;
}
impl Prepare for Arc<Block> {
fn prepare(self) -> SemanticallyVerifiedBlock {
self.into()
}
}
impl<T> From<T> for ChainTipBlock
where
T: Prepare,
{
fn from(block: T) -> Self {
block.prepare().into()
}
}
impl SemanticallyVerifiedBlock {
/// Returns a [`ContextuallyVerifiedBlock`] created from this block,
/// with fake zero-valued spent UTXOs.
///
/// Only for use in tests.
#[cfg(test)]
pub fn test_with_zero_spent_utxos(&self) -> ContextuallyVerifiedBlock {
ContextuallyVerifiedBlock::test_with_zero_spent_utxos(self)
}
/// Returns a [`ContextuallyVerifiedBlock`] created from this block,
/// with no chain value pool change.
///
/// Only for use in tests.
#[cfg(test)]
pub fn test_with_zero_chain_pool_change(&self) -> ContextuallyVerifiedBlock {
ContextuallyVerifiedBlock::test_with_zero_chain_pool_change(self)
}
}
impl ContextuallyVerifiedBlock {
/// Create a block that's ready for non-finalized `Chain` contextual
/// validation, using a [`SemanticallyVerifiedBlock`] and fake zero-valued spent UTXOs.
///
/// Only for use in tests.
pub fn test_with_zero_spent_utxos(block: impl Into<SemanticallyVerifiedBlock>) -> Self {
let block = block.into();
let zero_output = transparent::Output {
value: Amount::zero(),
lock_script: transparent::Script::new(&[]),
};
let zero_utxo = transparent::OrderedUtxo::new(zero_output, block::Height(1), 1);
let zero_spent_utxos = block
.block
.transactions
.iter()
.map(AsRef::as_ref)
.flat_map(Transaction::inputs)
.flat_map(transparent::Input::outpoint)
.map(|outpoint| (outpoint, zero_utxo.clone()))
.collect();
ContextuallyVerifiedBlock::with_block_and_spent_utxos(block, zero_spent_utxos)
.expect("all UTXOs are provided with zero values")
}
/// Create a [`ContextuallyVerifiedBlock`] from a [`Block`] or [`SemanticallyVerifiedBlock`],
/// with no chain value pool change.
///
/// Only for use in tests.
pub fn test_with_zero_chain_pool_change(block: impl Into<SemanticallyVerifiedBlock>) -> Self {
let SemanticallyVerifiedBlock {
block,
hash,
height,
new_outputs,
transaction_hashes,
deferred_pool_balance_change: _,
} = block.into();
Self {
block,
hash,
height,
new_outputs: new_outputs.clone(),
// Just re-use the outputs we created in this block, even though that's incorrect.
//
// TODO: fix the tests, and stop adding unrelated inputs and outputs.
spent_outputs: new_outputs,
transaction_hashes,
chain_value_pool_change: ValueBalance::zero(),
}
}
}