Use Bytes for block hash (instead of String)
This commit is contained in:
parent
c7f138ec90
commit
c68a6fdedb
|
@ -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"
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
11
src/index.rs
11
src/index.rs
|
@ -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,
|
||||
|
|
|
@ -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};
|
||||
|
|
15
src/store.rs
15
src/store.rs
|
@ -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
10
src/util.rs
Normal 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
|
||||
}
|
Loading…
Reference in New Issue
Block a user