-
Notifications
You must be signed in to change notification settings - Fork 55
/
block.rs
59 lines (54 loc) · 1.72 KB
/
block.rs
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
use preamble::*;
#[derive(PartialEq, Eq, Debug, Clone, Copy)]
pub struct Block<'a>(&'a [u8]);
impl<'a> Block<'a> {
pub fn read(slice: &mut &'a [u8]) -> ParseResult<Option<Block<'a>>> {
while slice.len() > 0 && slice[0] == 0 {
*slice = &slice[1..];
}
if slice.len() == 0 {
Ok(None)
} else {
let block_magic = read_u32(slice)?;
match block_magic {
// Incomplete blk file
0x00 => Ok(None),
// Bitcoin magic value
0xd9b4bef9 => {
let block_len = read_u32(slice)? as usize;
if block_len < 80 {
Err(ParseError::Eof)
} else {
Ok(Some(Block(read_slice(slice, block_len)?)))
}
}
_ => Err(ParseError::Invalid),
}
}
}
pub fn header(&self) -> BlockHeader<'a> {
let mut slice = self.0;
BlockHeader::new(read_array!(&mut slice, 80).unwrap())
}
pub fn transactions(&self) -> Result<Transactions<'a>> {
Transactions::new(&self.0[80..])
}
pub fn walk<V: BlockChainVisitor<'a>>(
&self,
visitor: &mut V,
height: u64,
output_items: &mut HashMap<Hash, VecMap<V::OutputItem>>,
) -> ParseResult<()> {
let header = self.header();
let mut block_item = visitor.visit_block_begin(*self, height);
self.transactions()?.walk(
visitor,
header.timestamp(),
height,
&mut block_item,
output_items,
)?;
visitor.visit_block_end(*self, height, block_item);
Ok(())
}
}