Use Bytes for block hash (instead of String)

This commit is contained in:
Roman Zeyde 2018-04-11 18:44:48 +03:00
parent c7f138ec90
commit c68a6fdedb
No known key found for this signature in database
GPG Key ID: 87CAE5FA46917CBB
6 changed files with 36 additions and 32 deletions

View File

@ -12,7 +12,6 @@ pbr = "1.0.0"
reqwest = "0.8.5" reqwest = "0.8.5"
rocksdb = "0.10.0" #{ path = "../../rust-rocksdb" } rocksdb = "0.10.0" #{ path = "../../rust-rocksdb" }
rust-crypto = "^0.2" rust-crypto = "^0.2"
rustc-serialize = "0.3"
serde_json = "1.0.13" serde_json = "1.0.13"
simple_logger = "0.5" simple_logger = "0.5"
time = "0.1.39" time = "0.1.39"

View File

@ -2,17 +2,18 @@ use bitcoin::blockdata::block::BlockHeader;
use bitcoin::network::encodable::ConsensusDecodable; use bitcoin::network::encodable::ConsensusDecodable;
use bitcoin::network::serialize::BitcoinHash; use bitcoin::network::serialize::BitcoinHash;
use bitcoin::network::serialize::RawDecoder; use bitcoin::network::serialize::RawDecoder;
use bitcoin::util::hash::Sha256dHash;
use itertools::enumerate; use itertools::enumerate;
use reqwest; use reqwest;
use std::collections::{HashMap, VecDeque}; use std::collections::{HashMap, VecDeque};
use std::io::Cursor; use std::io::Cursor;
use util;
use Bytes; use Bytes;
const HEADER_SIZE: usize = 80; const HEADER_SIZE: usize = 80;
type HeaderMap = HashMap<String, BlockHeader>; type HeaderMap = HashMap<Bytes, BlockHeader>;
pub struct Daemon { pub struct Daemon {
url: String, url: String,
@ -37,19 +38,22 @@ impl Daemon {
buf buf
} }
fn get_headers(&self) -> (HeaderMap, String) { fn get_headers(&self) -> (HeaderMap, Bytes) {
let mut headers = HashMap::new(); let mut headers = HashMap::new();
let mut blockhash = let mut blockhash: Bytes = vec![
String::from("000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"); // genesis 111, 226, 140, 10, 182, 241, 179, 114, 193, 166, 162, 70, 174, 99, 247, 79, 147, 30,
131, 101, 225, 90, 8, 156, 104, 214, 25, 0, 0, 0, 0, 0,
]; // genesis block hash
loop { loop {
let data = self.get(&format!("headers/2000/{}.bin", blockhash)); let data = self.get(&format!("headers/2000/{}.bin", util::revhex(&blockhash)));
assert!(!data.is_empty());
let num_of_headers = data.len() / HEADER_SIZE; let num_of_headers = data.len() / HEADER_SIZE;
let mut decoder = RawDecoder::new(Cursor::new(data)); let mut decoder = RawDecoder::new(Cursor::new(data));
for _ in 0..num_of_headers { for _ in 0..num_of_headers {
let header: BlockHeader = let header: BlockHeader =
ConsensusDecodable::consensus_decode(&mut decoder).unwrap(); ConsensusDecodable::consensus_decode(&mut decoder).unwrap();
blockhash = header.bitcoin_hash().be_hex_string(); blockhash = header.bitcoin_hash()[..].to_vec();
headers.insert(blockhash.to_string(), header); headers.insert(blockhash.clone(), header);
} }
if num_of_headers == 1 { if num_of_headers == 1 {
break; break;
@ -58,15 +62,15 @@ impl Daemon {
(headers, blockhash) (headers, blockhash)
} }
pub fn enumerate_headers(&self) -> Vec<(usize, String)> { pub fn enumerate_headers(&self) -> Vec<(usize, Bytes)> {
let (headers, mut blockhash) = self.get_headers(); let (headers, mut blockhash) = self.get_headers();
let mut hashes = VecDeque::<String>::new(); let mut hashes = VecDeque::<Bytes>::new();
let null_hash = Sha256dHash::default().be_hex_string(); let null_hash = [0u8; 32];
while blockhash != null_hash { while blockhash != null_hash {
let header: &BlockHeader = headers.get(&blockhash).unwrap(); let header: &BlockHeader = headers.get(&blockhash).unwrap();
hashes.push_front(blockhash); hashes.push_front(blockhash);
blockhash = header.prev_blockhash.be_hex_string(); blockhash = header.prev_blockhash[..].to_vec();
} }
enumerate(hashes).collect() enumerate(hashes).collect()
} }

View File

@ -10,6 +10,7 @@ use daemon::Daemon;
use store::{Row, Store}; use store::{Row, Store};
use timer::Timer; use timer::Timer;
use pbr; use pbr;
use util;
use Bytes; use Bytes;
@ -75,9 +76,9 @@ fn index_block(block: &Block, height: usize) -> Vec<Row> {
rows rows
} }
fn get_missing_hashes(store: &Store, daemon: &Daemon) -> Vec<(usize, String)> { fn get_missing_hashes(store: &Store, daemon: &Daemon) -> Vec<(usize, Bytes)> {
let indexed_headers = store.read_headers(); let indexed_headers = store.read_headers();
let mut hashes: Vec<(usize, String)> = daemon.enumerate_headers(); let mut hashes: Vec<(usize, Bytes)> = daemon.enumerate_headers();
info!( info!(
"got {} headers (indexed {})", "got {} headers (indexed {})",
hashes.len(), hashes.len(),
@ -102,11 +103,11 @@ pub fn update(store: &mut Store, daemon: &Daemon) {
let mut pb = pbr::ProgressBar::new(hashes.len() as u64); let mut pb = pbr::ProgressBar::new(hashes.len() as u64);
for (height, blockhash) in hashes { for (height, blockhash) in hashes {
timer.start("get"); timer.start("get");
let buf: Bytes = daemon.get(&format!("block/{}.bin", &blockhash)); let buf: Bytes = daemon.get(&format!("block/{}.bin", util::revhex(&blockhash)));
timer.start("parse"); timer.start("parse");
let block: Block = deserialize(&buf).unwrap(); let block: Block = deserialize(&buf).unwrap();
assert_eq!(&block.bitcoin_hash().be_hex_string(), &blockhash); assert_eq!(&block.bitcoin_hash()[..], blockhash.as_slice());
timer.start("index"); timer.start("index");
let rows = index_block(&block, height); let rows = index_block(&block, height);
@ -124,7 +125,7 @@ pub fn update(store: &mut Store, daemon: &Daemon) {
pb.inc(); pb.inc();
debug!( debug!(
"{} @ {}: {:.3}/{:.3} MB, {} rows, {}", "{} @ {}: {:.3}/{:.3} MB, {} rows, {}",
blockhash, util::revhex(&blockhash),
height, height,
rows_size as f64 / 1e6_f64, rows_size as f64 / 1e6_f64,
blocks_size as f64 / 1e6_f64, blocks_size as f64 / 1e6_f64,

View File

@ -12,10 +12,11 @@ extern crate zmq;
#[macro_use] #[macro_use]
extern crate log; extern crate log;
mod index;
mod daemon; mod daemon;
mod index;
mod store; mod store;
mod timer; mod timer;
mod util;
mod waiter; mod waiter;
use store::{Store, StoreOptions}; use store::{Store, StoreOptions};

View File

@ -1,7 +1,6 @@
use bitcoin::blockdata::block::BlockHeader; use bitcoin::blockdata::block::BlockHeader;
use bitcoin::network::serialize::deserialize; use bitcoin::network::serialize::deserialize;
use rocksdb; use rocksdb;
use std::char::from_digit;
use std::collections::HashMap; use std::collections::HashMap;
use time::{Duration, PreciseTime}; use time::{Duration, PreciseTime};
@ -22,15 +21,6 @@ pub struct StoreOptions {
pub auto_compact: bool, pub auto_compact: bool,
} }
fn revhex(data: &[u8]) -> String {
let mut ret = String::with_capacity(data.len() * 2);
for item in data.iter().rev() {
ret.push(from_digit((*item / 0x10) as u32, 16).unwrap());
ret.push(from_digit((*item & 0x0f) as u32, 16).unwrap());
}
ret
}
impl Store { impl Store {
/// Opens a new RocksDB at the specified location. /// Opens a new RocksDB at the specified location.
pub fn open(path: &str, opts: StoreOptions) -> Store { pub fn open(path: &str, opts: StoreOptions) -> Store {
@ -76,12 +66,11 @@ impl Store {
self.start = PreciseTime::now(); self.start = PreciseTime::now();
} }
pub fn read_headers(&self) -> HashMap<String, BlockHeader> { pub fn read_headers(&self) -> HashMap<Bytes, BlockHeader> {
let mut headers = HashMap::new(); let mut headers = HashMap::new();
for row in self.scan(b"B") { for row in self.scan(b"B") {
let blockhash = revhex(&row.key);
let header: BlockHeader = deserialize(&row.value).unwrap(); let header: BlockHeader = deserialize(&row.value).unwrap();
headers.insert(blockhash, header); headers.insert(row.key, header);
} }
headers headers
} }

10
src/util.rs Normal file
View File

@ -0,0 +1,10 @@
use std::char::from_digit;
pub fn revhex(data: &[u8]) -> String {
let mut ret = String::with_capacity(data.len() * 2);
for item in data.iter().rev() {
ret.push(from_digit((*item / 0x10) as u32, 16).unwrap());
ret.push(from_digit((*item & 0x0f) as u32, 16).unwrap());
}
ret
}