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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
use super::*;
/// Errors that prevent the header-sync reactor from starting.
#[derive(Debug, Error)]
pub enum HeaderSyncStartError {
/// The configured anchor is neither genesis nor a hash-matching checkpoint.
#[error("invalid Zakura header-sync anchor at height {anchor:?}")]
InvalidAnchor {
/// Rejected anchor.
anchor: (block::Height, block::Hash),
},
/// Only one anchor field was configured.
#[error("Zakura header-sync anchor_height and anchor_hash must be configured together")]
IncompleteAnchor,
}
/// Structured wire and stateless-validation errors for versioned header sync.
#[derive(Debug, Error)]
pub enum HeaderSyncWireError {
/// A payload or peer-controlled count exceeded its cap.
#[error("Zakura header-sync payload length {actual} exceeds cap {max}")]
OversizedPayload {
/// Actual payload length.
actual: usize,
/// Maximum allowed payload length.
max: usize,
},
/// A decoded header count exceeded its contract.
#[error("Zakura header-sync header count {actual} exceeds cap {max}")]
HeaderCountLimit {
/// Actual header count.
actual: usize,
/// Maximum allowed header count.
max: usize,
},
/// A locally constructed `Headers` message had a different number of size hints.
#[error("Zakura header-sync Headers body-size count {body_sizes} does not match header count {headers}")]
BodySizeCountMismatch {
/// Header count.
headers: usize,
/// Body-size hint count.
body_sizes: usize,
},
/// A locally constructed or inbound `Headers` message did not carry exactly one root per header.
#[error("Zakura header-sync Headers tree-aux root count {roots} does not match header count {headers}")]
TreeAuxRootCountMismatch {
/// Header count.
headers: usize,
/// Tree-aux root count.
roots: usize,
},
/// An inbound `Headers` response carried a root for the wrong height.
#[error(
"Zakura header-sync Headers tree-aux root height {root_height:?} does not match \
expected height {expected_height:?} at offset {offset} \
(first={first_root_height:?}, last={last_root_height:?})"
)]
TreeAuxRootHeightMismatch {
/// Zero-based root offset within the response.
offset: usize,
/// Expected root height.
expected_height: block::Height,
/// Actual root height.
root_height: block::Height,
/// First encoded root height.
first_root_height: block::Height,
/// Last encoded root height.
last_root_height: block::Height,
},
/// A boolean marker field used a value other than 0 or 1.
#[error("Zakura header-sync {field} marker has invalid value {value}")]
InvalidBoolMarker {
/// Marker field name.
field: &'static str,
/// Invalid marker value.
value: u8,
},
/// A peer returned tree-aux roots for a request that opted out.
#[error("Zakura header-sync Headers included tree-aux roots for an opt-out request")]
UnrequestedTreeAuxRoots,
/// An inbound `Headers` response did not match an in-flight request.
#[error("unsolicited Zakura header-sync Headers response")]
UnsolicitedHeaders,
/// A request-id capable header-sync message was missing its request ID.
#[error("Zakura header-sync v7 {message} message is missing a request ID")]
MissingRequestId {
/// Message that required the ID.
message: &'static str,
},
/// A `GetHeaders` request asked for zero headers.
#[error("Zakura header-sync GetHeaders count must be non-zero")]
ZeroHeaderRequestCount,
/// A height exceeded Zebra's supported height range.
#[error("Zakura header-sync height {0} exceeds supported range")]
HeightOutOfRange(u32),
/// A payload used an unknown header-sync message discriminator.
#[error("unknown Zakura header-sync message type {0}")]
UnknownMessageType(u8),
/// A frame used a message type that does not fit header sync's u8 discriminator.
#[error("unknown Zakura header-sync frame message type {0}")]
UnknownFrameMessageType(u16),
/// Frame flags are reserved in header sync.
#[error("unsupported Zakura header-sync frame flags {0}")]
UnsupportedFlags(u16),
/// Frame and payload message types disagreed.
#[error("Zakura header-sync frame type {frame} disagrees with payload type {payload}")]
MismatchedFrameMessageType {
/// Outer frame message type.
frame: u16,
/// Inner payload message type.
payload: u8,
},
/// A decoded payload had trailing bytes.
#[error("trailing bytes in Zakura header-sync payload")]
TrailingBytes,
/// Adjacent headers did not hash-link.
#[error("non-contiguous Zakura header-sync header run")]
NonContiguousHeaders,
/// The first header in a range did not link to its anchor.
#[error("first Zakura header-sync range header does not link to anchor")]
FirstHeaderDoesNotLink,
/// Equihash solution size did not match the active network.
#[error("Zakura header-sync Equihash solution size does not match the active network")]
WrongEquihashSolutionSize,
/// The compact difficulty threshold did not expand to a valid target.
#[error("invalid Zakura header-sync compact difficulty threshold")]
InvalidDifficultyThreshold,
/// The header hash failed the context-free difficulty filter.
#[error("Zakura header-sync hash {hash:?} exceeds difficulty threshold {threshold:?}")]
DifficultyFilter {
/// Header hash.
hash: block::Hash,
/// Expanded threshold from the header.
threshold: ExpandedDifficulty,
},
/// A numeric conversion failed while handling bounded data.
#[error("numeric overflow while encoding Zakura header-sync {0}")]
NumericOverflow(&'static str),
/// An I/O error while encoding or decoding.
#[error("Zakura header-sync wire I/O error: {0}")]
Io(#[from] io::Error),
/// Zcash serialization failed.
#[error("Zakura header-sync Zcash serialization error: {0}")]
Serialization(#[from] SerializationError),
/// Header time was too far in the future.
#[error(transparent)]
Time(#[from] BlockTimeError),
/// Equihash verification failed.
#[error(transparent)]
Equihash(#[from] equihash::Error),
/// The blocking validation task failed.
#[error("Zakura header-sync blocking validation task failed: {0}")]
BlockingTask(#[from] JoinError),
}