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"
rocksdb = "0.10.0" #{ path = "../../rust-rocksdb" }
rust-crypto = "^0.2"
rustc-serialize = "0.3"
serde_json = "1.0.13"
simple_logger = "0.5"
time = "0.1.39"

View File

@ -2,17 +2,18 @@ use bitcoin::blockdata::block::BlockHeader;
use bitcoin::network::encodable::ConsensusDecodable;
use bitcoin::network::serialize::BitcoinHash;
use bitcoin::network::serialize::RawDecoder;
use bitcoin::util::hash::Sha256dHash;
use itertools::enumerate;
use reqwest;
use std::collections::{HashMap, VecDeque};
use std::io::Cursor;
use util;
use Bytes;
const HEADER_SIZE: usize = 80;
type HeaderMap = HashMap<String, BlockHeader>;
type HeaderMap = HashMap<Bytes, BlockHeader>;
pub struct Daemon {
url: String,
@ -37,19 +38,22 @@ impl Daemon {
buf
}
fn get_headers(&self) -> (HeaderMap, String) {
fn get_headers(&self) -> (HeaderMap, Bytes) {
let mut headers = HashMap::new();
let mut blockhash =
String::from("000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"); // genesis
let mut blockhash: Bytes = vec![
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 {
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 mut decoder = RawDecoder::new(Cursor::new(data));
for _ in 0..num_of_headers {
let header: BlockHeader =
ConsensusDecodable::consensus_decode(&mut decoder).unwrap();
blockhash = header.bitcoin_hash().be_hex_string();
headers.insert(blockhash.to_string(), header);
blockhash = header.bitcoin_hash()[..].to_vec();
headers.insert(blockhash.clone(), header);
}
if num_of_headers == 1 {
break;
@ -58,15 +62,15 @@ impl Daemon {
(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 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 {
let header: &BlockHeader = headers.get(&blockhash).unwrap();
hashes.push_front(blockhash);
blockhash = header.prev_blockhash.be_hex_string();
blockhash = header.prev_blockhash[..].to_vec();
}
enumerate(hashes).collect()
}

View File

@ -10,6 +10,7 @@ use daemon::Daemon;
use store::{Row, Store};
use timer::Timer;
use pbr;
use util;
use Bytes;
@ -75,9 +76,9 @@ fn index_block(block: &Block, height: usize) -> Vec<Row> {
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 mut hashes: Vec<(usize, String)> = daemon.enumerate_headers();
let mut hashes: Vec<(usize, Bytes)> = daemon.enumerate_headers();
info!(
"got {} headers (indexed {})",
hashes.len(),
@ -102,11 +103,11 @@ pub fn update(store: &mut Store, daemon: &Daemon) {
let mut pb = pbr::ProgressBar::new(hashes.len() as u64);
for (height, blockhash) in hashes {
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");
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");
let rows = index_block(&block, height);
@ -124,7 +125,7 @@ pub fn update(store: &mut Store, daemon: &Daemon) {
pb.inc();
debug!(
"{} @ {}: {:.3}/{:.3} MB, {} rows, {}",
blockhash,
util::revhex(&blockhash),
height,
rows_size as f64 / 1e6_f64,
blocks_size as f64 / 1e6_f64,

View File

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

View File

@ -1,7 +1,6 @@
use bitcoin::blockdata::block::BlockHeader;
use bitcoin::network::serialize::deserialize;
use rocksdb;
use std::char::from_digit;
use std::collections::HashMap;
use time::{Duration, PreciseTime};
@ -22,15 +21,6 @@ pub struct StoreOptions {
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 {
/// Opens a new RocksDB at the specified location.
pub fn open(path: &str, opts: StoreOptions) -> Store {
@ -76,12 +66,11 @@ impl Store {
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();
for row in self.scan(b"B") {
let blockhash = revhex(&row.key);
let header: BlockHeader = deserialize(&row.value).unwrap();
headers.insert(blockhash, header);
headers.insert(row.key, header);
}
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
}