diff --git a/src/bulk.rs b/src/bulk.rs index 7674611..7a7b8c8 100644 --- a/src/bulk.rs +++ b/src/bulk.rs @@ -5,7 +5,7 @@ use bitcoin_hashes::sha256d::Hash as Sha256dHash; use libc; use std::collections::HashSet; use std::fs; -use std::io::{Cursor, Seek, SeekFrom}; +use std::io::Cursor; use std::path::{Path, PathBuf}; use std::sync::{ mpsc::{Receiver, SyncSender}, @@ -120,40 +120,37 @@ fn parse_blocks(blob: Vec, magic: u32) -> Result> { let mut blocks = vec![]; let max_pos = blob.len() as u64; while cursor.position() < max_pos { + let offset = cursor.position(); match u32::consensus_decode(&mut cursor) { Ok(value) => { if magic != value { - cursor - .seek(SeekFrom::Current(-3)) - .expect("failed to seek back"); + cursor.set_position(offset + 1); continue; } } Err(_) => break, // EOF }; let block_size = u32::consensus_decode(&mut cursor).chain_err(|| "no block size")?; - let start = cursor.position() as usize; - cursor - .seek(SeekFrom::Current(i64::from(block_size))) - .chain_err(|| format!("seek {} failed", block_size))?; - let end = cursor.position() as usize; + let start = cursor.position(); + let end = start + block_size as u64; - // If Core's WriteBlockToDisk ftell fails, only the magic byte and size will be written - // and the block body will be unwritten data. skip that's data. - let mut tmp_cursor = Cursor::new(&blob[start..(start + 4)]); - match u32::consensus_decode(&mut tmp_cursor) { + // If Core's WriteBlockToDisk ftell fails, only the magic bytes and size will be written + // and the block body won't be written to the blk*.dat file. + // Since the first 4 bytes should contain the block's version, we can skip such blocks + // by peeking the cursor (and skipping previous `magic` and `block_size`). + match u32::consensus_decode(&mut cursor) { Ok(value) => { if magic == value { - cursor.set_position(start as u64); + cursor.set_position(start); continue; } } Err(_) => break, // EOF } - - let block: Block = deserialize(&blob[start..end]) + let block: Block = deserialize(&blob[start as usize..end as usize]) .chain_err(|| format!("failed to parse block at {}..{}", start, end))?; blocks.push(block); + cursor.set_position(end as u64); } Ok(blocks) }