1use primitive_types::U256;
2
3#[derive(Debug, PartialEq, Eq, Clone)]
5pub enum SPVError {
6 ReadOverrun,
8 BadCompactInt,
10 MalformattedOpReturnOutput,
12 MalformattedP2SHOutput,
14 MalformattedP2PKHOutput,
16 MalformattedWitnessOutput,
18 MalformattedOutput,
20 WrongLengthHeader,
22 UnexpectedDifficultyChange,
24 InsufficientWork,
26 InvalidChain,
28 WrongDigest,
31 WrongMerkleRoot,
34 WrongPrevHash,
37 InvalidVin,
39 InvalidVout,
41 WrongTxID,
44 BadMerkleProof,
47 OutputLengthMismatch,
49 UnknownError,
51}
52
53#[derive(Debug, Clone, PartialEq, Eq, PartialOrd)]
55pub enum PayloadType<'a> {
56 PKH(&'a [u8]),
58 SH(&'a [u8]),
60 WPKH(&'a [u8]),
62 WSH(&'a [u8]),
64}
65
66impl PartialEq<[u8]> for PayloadType<'_> {
67 fn eq(&self, other: &[u8]) -> bool {
68 match self {
69 PayloadType::PKH(slice) => *slice == other,
70 PayloadType::SH(slice) => *slice == other,
71 PayloadType::WPKH(slice) => *slice == other,
72 PayloadType::WSH(slice) => *slice == other,
73 }
74 }
75}
76
77impl PartialEq<&[u8]> for PayloadType<'_> {
78 fn eq(&self, other: &&[u8]) -> bool {
79 match self {
80 PayloadType::PKH(slice) => slice == other,
81 PayloadType::SH(slice) => slice == other,
82 PayloadType::WPKH(slice) => slice == other,
83 PayloadType::WSH(slice) => slice == other,
84 }
85 }
86}
87
88#[derive(Copy, Clone)]
90pub struct RawHeader([u8; 80]);
91
92impl PartialEq for RawHeader {
93 fn eq(&self, other: &Self) -> bool {
94 self.0[..] == other.0[..]
95 }
96}
97
98impl Eq for RawHeader {}
99
100impl RawHeader {
101 pub fn new<T: AsRef<[u8]>>(buf: &T) -> Result<Self, SPVError> {
104 if buf.as_ref().len() < 80 {
105 return Err(SPVError::WrongLengthHeader);
106 }
107 let mut header = Self::default();
108 header.as_mut().copy_from_slice(&buf.as_ref()[..80]);
109 Ok(header)
110 }
111
112 pub fn digest(&self) -> Hash256Digest {
114 crate::btcspv::hash256(&[self.as_ref()])
115 }
116
117 pub fn tx_root(&self) -> Hash256Digest {
119 crate::btcspv::extract_merkle_root_le(*self)
120 }
121
122 pub fn target(&self) -> U256 {
124 crate::btcspv::extract_target(*self)
125 }
126
127 pub fn difficulty(&self) -> U256 {
129 crate::btcspv::extract_difficulty(*self)
130 }
131
132 pub fn timestamp(&self) -> u32 {
134 crate::btcspv::extract_timestamp(*self)
135 }
136
137 pub fn parent(&self) -> Hash256Digest {
139 crate::btcspv::extract_prev_block_hash_le(*self)
140 }
141}
142
143impl Default for RawHeader {
144 fn default() -> Self {
145 Self([0u8; 80])
146 }
147}
148
149impl From<[u8; 80]> for RawHeader {
150 fn from(buf: [u8; 80]) -> Self {
151 Self(buf)
152 }
153}
154
155impl AsRef<[u8; 80]> for RawHeader {
156 fn as_ref(&self) -> &[u8; 80] {
157 &self.0
158 }
159}
160
161impl AsMut<[u8; 80]> for RawHeader {
162 fn as_mut(&mut self) -> &mut [u8; 80] {
163 &mut self.0
164 }
165}
166
167impl<I: core::slice::SliceIndex<[u8]>> core::ops::Index<I> for RawHeader {
168 type Output = I::Output;
169
170 fn index(&self, index: I) -> &Self::Output {
171 self.as_ref().index(index)
172 }
173}
174
175#[derive(Clone, PartialEq, Eq, Hash)]
177pub struct HeaderArray<'a>(&'a [u8]);
178
179#[cfg_attr(tarpaulin, skip)]
180impl core::fmt::Debug for HeaderArray<'_> {
181 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
187 write!(
188 f,
189 "HeaderArray: {:x?}", self.0
190 )
191 }
192}
193
194impl<'a> HeaderArray<'a> {
195 pub fn new(slice: &'a [u8]) -> Result<HeaderArray<'a>, SPVError> {
197 if slice.len() % 80 == 0 {
198 Ok(Self(slice))
199 } else {
200 Err(SPVError::WrongLengthHeader)
201 }
202 }
203}
204
205impl HeaderArray<'_> {
206 pub fn len(&self) -> usize {
208 self.0.len() / 80
209 }
210
211 pub fn is_empty(&self) -> bool {
213 self.0.is_empty()
214 }
215
216 pub fn index(&self, index: usize) -> RawHeader {
219 let mut header = RawHeader::default();
220 header
221 .as_mut()
222 .copy_from_slice(&self.0[index * 80..(index + 1) * 80]);
223 header
224 }
225
226 pub fn valid_difficulty(&self, constant_difficulty: bool) -> Result<U256, SPVError> {
228 crate::validatespv::validate_header_chain(self, constant_difficulty)
229 }
230
231 pub fn iter(&self) -> HeaderArrayIter {
233 HeaderArrayIter::new(&self)
234 }
235}
236
237pub struct HeaderArrayIter<'a> {
239 next_index: usize,
240 headers: &'a HeaderArray<'a>,
241}
242
243impl<'a> HeaderArrayIter<'a> {
244 fn new(headers: &'a HeaderArray<'a>) -> Self {
245 Self {
246 next_index: 0,
247 headers,
248 }
249 }
250}
251
252impl<'a> Iterator for HeaderArrayIter<'a> {
253 type Item = RawHeader;
254
255 fn next(&mut self) -> Option<Self::Item> {
256 if self.next_index == self.headers.len() {
257 return None;
258 }
259 let header = self.headers.index(self.next_index);
260 self.next_index += 1;
261 Some(header)
262 }
263}
264
265#[derive(Copy, Clone, PartialEq, Eq, Default, Hash)]
267pub struct Hash256Digest([u8; 32]);
268
269#[cfg_attr(tarpaulin, skip)]
270impl core::fmt::Debug for Hash256Digest {
271 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
272 write!(
273 f,
274 "Hash256Digest: {:x?}", self.0
275 )
276 }
277}
278
279
280impl From<[u8; 32]> for Hash256Digest {
281 fn from(buf: [u8; 32]) -> Self {
282 Self(buf)
283 }
284}
285
286impl AsRef<[u8; 32]> for Hash256Digest {
287 fn as_ref(&self) -> &[u8; 32] {
288 &self.0
289 }
290}
291
292impl AsMut<[u8; 32]> for Hash256Digest {
293 fn as_mut(&mut self) -> &mut [u8; 32] {
294 &mut self.0
295 }
296}
297
298#[derive(Copy, Clone, PartialEq, Eq, Default, Hash)]
300pub struct Hash160Digest([u8; 20]);
301
302#[cfg_attr(tarpaulin, skip)]
303impl core::fmt::Debug for Hash160Digest {
304 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
310 write!(
311 f,
312 "Hash160Digest: {:x?}", self.0
313 )
314 }
315}
316
317impl From<[u8; 20]> for Hash160Digest {
318 fn from(buf: [u8; 20]) -> Self {
319 Self(buf)
320 }
321}
322
323impl AsRef<[u8; 20]> for Hash160Digest {
324 fn as_ref(&self) -> &[u8; 20] {
325 &self.0
326 }
327}
328
329impl AsMut<[u8; 20]> for Hash160Digest {
330 fn as_mut(&mut self) -> &mut [u8; 20] {
331 &mut self.0
332 }
333}
334
335#[derive(Debug, Clone, PartialEq, Eq)]
337pub struct MerkleArray<'a>(&'a [u8]);
338
339impl<'a> MerkleArray<'a> {
340 pub fn new(slice: &'a [u8]) -> Result<MerkleArray<'a>, SPVError> {
342 if slice.len() % 32 == 0 {
343 Ok(Self(slice))
344 } else {
345 Err(SPVError::BadMerkleProof)
346 }
347 }
348}
349
350impl MerkleArray<'_> {
351 pub fn len(&self) -> usize {
353 self.0.len() / 32
354 }
355
356 pub fn is_empty(&self) -> bool {
358 self.0.is_empty()
359 }
360
361 pub fn index(&self, index: usize) -> Hash256Digest {
363 let mut digest = Hash256Digest::default();
364 digest
365 .as_mut()
366 .copy_from_slice(&self.0[index * 32..(index + 1) * 32]);
367 digest
368 }
369}
370
371#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
373pub struct CompactInt(u64);
374
375compact_int_conv!(u8);
376compact_int_conv!(u16);
377compact_int_conv!(u32);
378compact_int_conv!(u64);
379compact_int_conv!(usize);
380
381impl AsRef<u64> for CompactInt {
382 fn as_ref(&self) -> &u64 {
383 &self.0
384 }
385}
386
387impl CompactInt {
388 pub fn parse<T: AsRef<[u8]> + ?Sized>(t: &T) -> Result<CompactInt, SPVError> {
390 crate::btcspv::parse_compact_int(t)
391 }
392
393 pub fn number(&self) -> u64 {
395 self.0
396 }
397
398 pub fn as_usize(&self) -> usize {
400 self.0 as usize
401 }
402
403 pub fn serialized_length(&self) -> usize {
405 match self.0 {
406 0..=0xfc => 1,
407 0xfd..=0xffff => 3,
408 0x10000..=0xffff_ffff => 5,
409 _ => 9,
410 }
411 }
412
413 pub fn data_length(flag: u8) -> u8 {
420 let length: u8 = match flag {
421 0xfd => 2,
422 0xfe => 4,
423 0xff => 8,
424 _ => 0,
425 };
426 length
427 }
428}
429
430impl_view_type!(
431 ScriptSig
433);
434
435impl_view_type!(
436 Outpoint
438);
439
440impl Outpoint<'_> {
441 pub fn txid_le(&self) -> Hash256Digest {
443 crate::btcspv::extract_input_tx_id_le(self)
444 }
445
446 pub fn vout_index(&self) -> u32 {
448 crate::btcspv::extract_tx_index(self)
449 }
450}
451
452impl_view_type!(
453 TxIn
455);
456
457impl TxIn<'_> {
458 pub fn outpoint(&self) -> Outpoint {
460 crate::btcspv::extract_outpoint(self)
461 }
462
463 pub fn sequence(&self) -> u32 {
465 crate::btcspv::extract_sequence(self).expect("Not malformed")
466 }
467
468 pub fn script_sig(&self) -> ScriptSig {
470 crate::btcspv::extract_script_sig(self).expect("Not malformed")
471 }
472}
473
474impl_view_type!(
475 Vin
477);
478
479impl<'a> Vin<'a> {
480 pub fn new(slice: &'a [u8]) -> Result<Vin<'a>, SPVError> {
482 if crate::btcspv::validate_vin(slice) {
483 Ok(Self(slice))
484 } else {
485 Err(SPVError::InvalidVin)
486 }
487 }
488
489 pub fn index(&self, index: usize) -> Result<TxIn, SPVError> {
491 crate::btcspv::extract_input_at_index(self, index)
492 }
493}
494
495impl_view_type!(
496 ScriptPubkey
498);
499
500impl ScriptPubkey<'_> {
501 pub fn op_return(&self) -> Result<OpReturnPayload, SPVError> {
503 crate::btcspv::extract_op_return_data(self)
504 }
505
506 pub fn payload(&self) -> Result<PayloadType, SPVError> {
508 crate::btcspv::extract_hash(self)
509 }
510}
511
512impl_view_type!(
513 OpReturnPayload
515);
516
517impl_view_type!(
518 TxOut
520);
521
522impl TxOut<'_> {
523 pub fn value(&self) -> u64 {
525 crate::btcspv::extract_value(self)
526 }
527
528 pub fn script_pubkey(&self) -> ScriptPubkey {
530 crate::btcspv::extract_script_pubkey(self)
531 }
532}
533
534impl_view_type!(
535 Vout
537);
538
539impl<'a> Vout<'a> {
540 pub fn new(slice: &'a [u8]) -> Result<Vout<'a>, SPVError> {
542 if crate::btcspv::validate_vout(slice) {
543 Ok(Self(slice))
544 } else {
545 Err(SPVError::InvalidVout)
546 }
547 }
548
549 pub fn index(&self, index: usize) -> Result<TxOut, SPVError> {
551 crate::btcspv::extract_output_at_index(self, index)
552 }
553}